1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2016 Texas Instruments, Inc. 4 */ 5 6#include <common.h> 7#include <hang.h> 8#include <log.h> 9#include <linux/libfdt.h> 10#include <fdt_support.h> 11#include <malloc.h> 12 13#include <asm/omap_common.h> 14#include <asm/arch-omap5/sys_proto.h> 15 16#ifdef CONFIG_TI_SECURE_DEVICE 17 18/* Give zero values if not already defined */ 19#ifndef TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ 20#define TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ (0) 21#endif 22#ifndef CFG_SECURE_RUNTIME_RESV_SRAM_SZ 23#define CFG_SECURE_RUNTIME_RESV_SRAM_SZ (0) 24#endif 25 26static u32 hs_irq_skip[] = { 27 8, /* Secure violation reporting interrupt */ 28 15, /* One interrupt for SDMA by secure world */ 29 118 /* One interrupt for Crypto DMA by secure world */ 30}; 31 32static int ft_hs_fixup_crossbar(void *fdt, struct bd_info *bd) 33{ 34 const char *path; 35 int offs; 36 int ret; 37 int len, i, old_cnt, new_cnt; 38 u32 *temp; 39 const u32 *p_data; 40 41 /* 42 * Increase the size of the fdt 43 * so we have some breathing room 44 */ 45 ret = fdt_increase_size(fdt, 512); 46 if (ret < 0) { 47 printf("Could not increase size of device tree: %s\n", 48 fdt_strerror(ret)); 49 return ret; 50 } 51 52 /* Reserve IRQs that are used/needed by secure world */ 53 path = "/ocp/crossbar"; 54 offs = fdt_path_offset(fdt, path); 55 if (offs < 0) { 56 debug("Node %s not found.\n", path); 57 return 0; 58 } 59 60 /* Get current entries */ 61 p_data = fdt_getprop(fdt, offs, "ti,irqs-skip", &len); 62 if (p_data) 63 old_cnt = len / sizeof(u32); 64 else 65 old_cnt = 0; 66 67 new_cnt = sizeof(hs_irq_skip) / 68 sizeof(hs_irq_skip[0]); 69 70 /* Create new/updated skip list for HS parts */ 71 temp = malloc(sizeof(u32) * (old_cnt + new_cnt)); 72 for (i = 0; i < new_cnt; i++) 73 temp[i] = cpu_to_fdt32(hs_irq_skip[i]); 74 for (i = 0; i < old_cnt; i++) 75 temp[i + new_cnt] = p_data[i]; 76 77 /* Blow away old data and set new data */ 78 fdt_delprop(fdt, offs, "ti,irqs-skip"); 79 ret = fdt_setprop(fdt, offs, "ti,irqs-skip", 80 temp, 81 (old_cnt + new_cnt) * sizeof(u32)); 82 free(temp); 83 84 /* Check if the update worked */ 85 if (ret < 0) { 86 printf("Could not add ti,irqs-skip property to node %s: %s\n", 87 path, fdt_strerror(ret)); 88 return ret; 89 } 90 91 return 0; 92} 93 94#if ((TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ != 0) || \ 95 (CFG_SECURE_RUNTIME_RESV_SRAM_SZ != 0)) 96static int ft_hs_fixup_sram(void *fdt, struct bd_info *bd) 97{ 98 const char *path; 99 int offs; 100 int ret; 101 u32 temp[2]; 102 103 /* 104 * Update SRAM reservations on secure devices. The OCMC RAM 105 * is always reserved for secure use from the start of that 106 * memory region 107 */ 108 path = "/ocp/ocmcram@40300000/sram-hs"; 109 offs = fdt_path_offset(fdt, path); 110 if (offs < 0) { 111 debug("Node %s not found.\n", path); 112 return 0; 113 } 114 115 /* relative start offset */ 116 temp[0] = cpu_to_fdt32(0); 117 /* reservation size */ 118 temp[1] = cpu_to_fdt32(max(TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ, 119 CFG_SECURE_RUNTIME_RESV_SRAM_SZ)); 120 fdt_delprop(fdt, offs, "reg"); 121 ret = fdt_setprop(fdt, offs, "reg", temp, 2 * sizeof(u32)); 122 if (ret < 0) { 123 printf("Could not add reg property to node %s: %s\n", 124 path, fdt_strerror(ret)); 125 return ret; 126 } 127 128 return 0; 129} 130#else 131static int ft_hs_fixup_sram(void *fdt, struct bd_info *bd) { return 0; } 132#endif 133 134static void ft_hs_fixups(void *fdt, struct bd_info *bd) 135{ 136 /* Check we are running on an HS/EMU device type */ 137 if (GP_DEVICE != get_device_type()) { 138 if ((ft_hs_fixup_crossbar(fdt, bd) == 0) && 139 (ft_hs_disable_rng(fdt, bd) == 0) && 140 (ft_hs_fixup_sram(fdt, bd) == 0) && 141 (ft_hs_fixup_dram(fdt, bd) == 0) && 142 (ft_hs_add_tee(fdt, bd) == 0)) 143 return; 144 } else { 145 printf("ERROR: Incorrect device type (GP) detected!"); 146 } 147 /* Fixup failed or wrong device type */ 148 hang(); 149} 150#else 151static void ft_hs_fixups(void *fdt, struct bd_info *bd) 152{ 153} 154#endif /* #ifdef CONFIG_TI_SECURE_DEVICE */ 155 156#if defined(CONFIG_TARGET_DRA7XX_EVM) || defined(CONFIG_TARGET_AM57XX_EVM) 157#define OPP_DSP_CLK_NUM 3 158#define OPP_IVA_CLK_NUM 2 159#define OPP_GPU_CLK_NUM 2 160 161const char *dra7_opp_dsp_clk_names[OPP_DSP_CLK_NUM] = { 162 "dpll_dsp_ck", 163 "dpll_dsp_m2_ck", 164 "dpll_dsp_m3x2_ck", 165}; 166 167const char *dra7_opp_iva_clk_names[OPP_IVA_CLK_NUM] = { 168 "dpll_iva_ck", 169 "dpll_iva_m2_ck", 170}; 171 172const char *dra7_opp_gpu_clk_names[OPP_GPU_CLK_NUM] = { 173 "dpll_gpu_ck", 174 "dpll_gpu_m2_ck", 175}; 176 177/* DSPEVE voltage domain */ 178u32 dra7_opp_dsp_clk_rates[NUM_OPPS][OPP_DSP_CLK_NUM] = { 179 {}, /*OPP_LOW */ 180 {600000000, 600000000, 400000000}, /* OPP_NOM */ 181 {700000000, 700000000, 466666667}, /* OPP_OD */ 182 {750000000, 750000000, 500000000}, /* OPP_HIGH */ 183}; 184 185/* DSP clock rates on DRA76x ACD-package based SoCs */ 186u32 dra76_opp_dsp_clk_rates[NUM_OPPS][OPP_DSP_CLK_NUM] = { 187 {}, /* OPP_LOW */ 188 {600000000, 600000000, 400000000}, /* OPP_NOM */ 189 {700000000, 700000000, 466666667}, /* OPP_OD */ 190 {850000000, 850000000, 566666667}, /* OPP_HIGH */ 191}; 192 193/* IVA voltage domain */ 194u32 dra7_opp_iva_clk_rates[NUM_OPPS][OPP_IVA_CLK_NUM] = { 195 {}, /* OPP_LOW */ 196 {1165000000, 388333334}, /* OPP_NOM */ 197 {860000000, 430000000}, /* OPP_OD */ 198 {1064000000, 532000000}, /* OPP_HIGH */ 199}; 200 201/* GPU voltage domain */ 202u32 dra7_opp_gpu_clk_rates[NUM_OPPS][OPP_GPU_CLK_NUM] = { 203 {}, /* OPP_LOW */ 204 {1277000000, 425666667}, /* OPP_NOM */ 205 {1000000000, 500000000}, /* OPP_OD */ 206 {1064000000, 532000000}, /* OPP_HIGH */ 207}; 208 209static int fdt_clock_output_name_eq_(const void *fdt, int offset, 210 const char *s, int len) 211{ 212 int olen; 213 const char *p = fdt_getprop(fdt, offset, "clock-output-names", &olen); 214 215 if (!p) 216 /* short match */ 217 return 0; 218 219 if (memcmp(p, s, len) != 0) 220 return 0; 221 222 if (p[len] == '\0') 223 return 1; 224 else 225 return 0; 226} 227 228static int ft_fixup_clocks(void *fdt, const char **names, u32 *rates, int num) 229{ 230 int offs, node_offs, subnode, ret, i; 231 uint32_t phandle; 232 233 offs = fdt_path_offset(fdt, "/ocp/interconnect@4a000000/segment@0/target-module@5000/cm_core_aon@0/clocks"); 234 if (offs < 0) 235 offs = fdt_path_offset(fdt, "/ocp/l4@4a000000/cm_core_aon@5000/clocks"); 236 if (offs < 0) { 237 debug("Could not find cm_core_aon clocks node path offset : %s\n", 238 fdt_strerror(offs)); 239 return offs; 240 } 241 242 for (i = 0; i < num; i++) { 243 node_offs = fdt_subnode_offset(fdt, offs, names[i]); 244 if (node_offs < 0) { 245 for (subnode = fdt_first_subnode(fdt, offs); 246 subnode >= 0; 247 subnode = fdt_next_subnode(fdt, subnode)) { 248 ret = fdt_clock_output_name_eq_(fdt, subnode, names[i], 249 strlen(names[i])); 250 if (ret) 251 node_offs = subnode; 252 } 253 if (node_offs < 0) { 254 debug("Could not find clock sub-node %s: %s\n", 255 names[i], fdt_strerror(node_offs)); 256 return offs; 257 } 258 } 259 260 phandle = fdt_get_phandle(fdt, node_offs); 261 if (!phandle) { 262 debug("Could not find phandle for clock %s\n", 263 names[i]); 264 return -1; 265 } 266 267 ret = fdt_setprop_u32(fdt, node_offs, "assigned-clocks", 268 phandle); 269 if (ret < 0) { 270 debug("Could not add assigned-clocks property to clock node %s: %s\n", 271 names[i], fdt_strerror(ret)); 272 return ret; 273 } 274 275 ret = fdt_setprop_u32(fdt, node_offs, "assigned-clock-rates", 276 rates[i]); 277 if (ret < 0) { 278 debug("Could not add assigned-clock-rates property to clock node %s: %s\n", 279 names[i], fdt_strerror(ret)); 280 return ret; 281 } 282 } 283 284 return 0; 285} 286 287static void ft_opp_clock_fixups(void *fdt, struct bd_info *bd) 288{ 289 const char **clk_names; 290 u32 *clk_rates; 291 int ret; 292 293 if (!is_dra72x() && !is_dra7xx()) 294 return; 295 296 /* fixup DSP clocks */ 297 clk_names = dra7_opp_dsp_clk_names; 298 clk_rates = dra7_opp_dsp_clk_rates[get_voltrail_opp(VOLT_EVE)]; 299 /* adjust for higher OPP_HIGH clock rate on DRA76xP/DRA77xP SoCs */ 300 if (is_dra76x_acd()) 301 clk_rates = dra76_opp_dsp_clk_rates[get_voltrail_opp(VOLT_EVE)]; 302 303 ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_DSP_CLK_NUM); 304 if (ret) { 305 printf("ft_fixup_clocks failed for DSP voltage domain: %s\n", 306 fdt_strerror(ret)); 307 return; 308 } 309 310 /* fixup IVA clocks */ 311 clk_names = dra7_opp_iva_clk_names; 312 clk_rates = dra7_opp_iva_clk_rates[get_voltrail_opp(VOLT_IVA)]; 313 ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_IVA_CLK_NUM); 314 if (ret) { 315 printf("ft_fixup_clocks failed for IVA voltage domain: %s\n", 316 fdt_strerror(ret)); 317 return; 318 } 319 320 /* fixup GPU clocks */ 321 clk_names = dra7_opp_gpu_clk_names; 322 clk_rates = dra7_opp_gpu_clk_rates[get_voltrail_opp(VOLT_GPU)]; 323 ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_GPU_CLK_NUM); 324 if (ret) { 325 printf("ft_fixup_clocks failed for GPU voltage domain: %s\n", 326 fdt_strerror(ret)); 327 return; 328 } 329} 330#else 331static void ft_opp_clock_fixups(void *fdt, struct bd_info *bd) { } 332#endif /* CONFIG_TARGET_DRA7XX_EVM || CONFIG_TARGET_AM57XX_EVM */ 333 334/* 335 * Place for general cpu/SoC FDT fixups. Board specific 336 * fixups should remain in the board files which is where 337 * this function should be called from. 338 */ 339void ft_cpu_setup(void *fdt, struct bd_info *bd) 340{ 341 ft_hs_fixups(fdt, bd); 342 ft_opp_clock_fixups(fdt, bd); 343} 344