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 <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 CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ
  23#define CONFIG_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    (CONFIG_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                                   CONFIG_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 ft_fixup_clocks(void *fdt, const char **names, u32 *rates, int num)
 210{
 211        int offs, node_offs, ret, i;
 212        uint32_t phandle;
 213
 214        offs = fdt_path_offset(fdt, "/ocp/interconnect@4a000000/segment@0/target-module@5000/cm_core_aon@0/clocks");
 215        if (offs < 0)
 216                offs = fdt_path_offset(fdt, "/ocp/l4@4a000000/cm_core_aon@5000/clocks");
 217        if (offs < 0) {
 218                debug("Could not find cm_core_aon clocks node path offset : %s\n",
 219                      fdt_strerror(offs));
 220                return offs;
 221        }
 222
 223        for (i = 0; i < num; i++) {
 224                node_offs = fdt_subnode_offset(fdt, offs, names[i]);
 225                if (node_offs < 0) {
 226                        debug("Could not find clock sub-node %s: %s\n",
 227                              names[i], fdt_strerror(node_offs));
 228                        return offs;
 229                }
 230
 231                phandle = fdt_get_phandle(fdt, node_offs);
 232                if (!phandle) {
 233                        debug("Could not find phandle for clock %s\n",
 234                              names[i]);
 235                        return -1;
 236                }
 237
 238                ret = fdt_setprop_u32(fdt, node_offs, "assigned-clocks",
 239                                      phandle);
 240                if (ret < 0) {
 241                        debug("Could not add assigned-clocks property to clock node %s: %s\n",
 242                              names[i], fdt_strerror(ret));
 243                        return ret;
 244                }
 245
 246                ret = fdt_setprop_u32(fdt, node_offs, "assigned-clock-rates",
 247                                      rates[i]);
 248                if (ret < 0) {
 249                        debug("Could not add assigned-clock-rates property to clock node %s: %s\n",
 250                              names[i], fdt_strerror(ret));
 251                        return ret;
 252                }
 253        }
 254
 255        return 0;
 256}
 257
 258static void ft_opp_clock_fixups(void *fdt, struct bd_info *bd)
 259{
 260        const char **clk_names;
 261        u32 *clk_rates;
 262        int ret;
 263
 264        if (!is_dra72x() && !is_dra7xx())
 265                return;
 266
 267        /* fixup DSP clocks */
 268        clk_names = dra7_opp_dsp_clk_names;
 269        clk_rates = dra7_opp_dsp_clk_rates[get_voltrail_opp(VOLT_EVE)];
 270        /* adjust for higher OPP_HIGH clock rate on DRA76xP/DRA77xP SoCs */
 271        if (is_dra76x_acd())
 272                clk_rates = dra76_opp_dsp_clk_rates[get_voltrail_opp(VOLT_EVE)];
 273
 274        ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_DSP_CLK_NUM);
 275        if (ret) {
 276                printf("ft_fixup_clocks failed for DSP voltage domain: %s\n",
 277                       fdt_strerror(ret));
 278                return;
 279        }
 280
 281        /* fixup IVA clocks */
 282        clk_names = dra7_opp_iva_clk_names;
 283        clk_rates = dra7_opp_iva_clk_rates[get_voltrail_opp(VOLT_IVA)];
 284        ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_IVA_CLK_NUM);
 285        if (ret) {
 286                printf("ft_fixup_clocks failed for IVA voltage domain: %s\n",
 287                       fdt_strerror(ret));
 288                return;
 289        }
 290
 291        /* fixup GPU clocks */
 292        clk_names = dra7_opp_gpu_clk_names;
 293        clk_rates = dra7_opp_gpu_clk_rates[get_voltrail_opp(VOLT_GPU)];
 294        ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_GPU_CLK_NUM);
 295        if (ret) {
 296                printf("ft_fixup_clocks failed for GPU voltage domain: %s\n",
 297                       fdt_strerror(ret));
 298                return;
 299        }
 300}
 301#else
 302static void ft_opp_clock_fixups(void *fdt, struct bd_info *bd) { }
 303#endif /* CONFIG_TARGET_DRA7XX_EVM || CONFIG_TARGET_AM57XX_EVM */
 304
 305/*
 306 * Place for general cpu/SoC FDT fixups. Board specific
 307 * fixups should remain in the board files which is where
 308 * this function should be called from.
 309 */
 310void ft_cpu_setup(void *fdt, struct bd_info *bd)
 311{
 312        ft_hs_fixups(fdt, bd);
 313        ft_opp_clock_fixups(fdt, bd);
 314}
 315