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