uboot/board/synopsys/hsdk/hsdk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
   4 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
   5 */
   6
   7#include <common.h>
   8#include <command.h>
   9#include <config.h>
  10#include <cpu_func.h>
  11#include <env.h>
  12#include <image.h>
  13#include <init.h>
  14#include <irq_func.h>
  15#include <log.h>
  16#include <asm/cache.h>
  17#include <asm/global_data.h>
  18#include <linux/bitops.h>
  19#include <linux/delay.h>
  20#include <linux/printk.h>
  21#include <linux/kernel.h>
  22#include <linux/io.h>
  23#include <asm/arcregs.h>
  24#include <fdt_support.h>
  25#include <dwmmc.h>
  26#include <malloc.h>
  27#include <usb.h>
  28
  29#include "clk-lib.h"
  30#include "env-lib.h"
  31
  32DECLARE_GLOBAL_DATA_PTR;
  33
  34#define ALL_CPU_MASK            GENMASK(NR_CPUS - 1, 0)
  35#define MASTER_CPU_ID           0
  36#define APERTURE_SHIFT          28
  37#define NO_CCM                  0x10
  38#define SLAVE_CPU_READY         0x12345678
  39#define BOOTSTAGE_1             1 /* after SP, FP setup, before HW init */
  40#define BOOTSTAGE_2             2 /* after HW init, before self halt */
  41#define BOOTSTAGE_3             3 /* after self halt */
  42#define BOOTSTAGE_4             4 /* before app launch */
  43#define BOOTSTAGE_5             5 /* after app launch, unreachable */
  44
  45#define RESET_VECTOR_ADDR       0x0
  46
  47#define CREG_BASE               (ARC_PERIPHERAL_BASE + 0x1000)
  48#define CREG_CPU_START          (CREG_BASE + 0x400)
  49#define CREG_CPU_START_MASK     0xF
  50#define CREG_CPU_START_POL      BIT(4)
  51
  52#define CREG_CORE_BOOT_IMAGE    GENMASK(5, 4)
  53
  54#define CREG_CPU_0_ENTRY        (CREG_BASE + 0x404)
  55
  56#define SDIO_BASE               (ARC_PERIPHERAL_BASE + 0xA000)
  57#define SDIO_UHS_REG_EXT        (SDIO_BASE + 0x108)
  58#define SDIO_UHS_REG_EXT_DIV_2  (2 << 30)
  59
  60/* Uncached access macros */
  61#define arc_read_uncached_32(ptr)       \
  62({                                      \
  63        unsigned int __ret;             \
  64        __asm__ __volatile__(           \
  65        "       ld.di %0, [%1]  \n"     \
  66        : "=r"(__ret)                   \
  67        : "r"(ptr));                    \
  68        __ret;                          \
  69})
  70
  71#define arc_write_uncached_32(ptr, data)\
  72({                                      \
  73        __asm__ __volatile__(           \
  74        "       st.di %0, [%1]  \n"     \
  75        :                               \
  76        : "r"(data), "r"(ptr));         \
  77})
  78
  79struct hsdk_env_core_ctl {
  80        u32_env entry[NR_CPUS];
  81        u32_env iccm[NR_CPUS];
  82        u32_env dccm[NR_CPUS];
  83};
  84
  85struct hsdk_env_common_ctl {
  86        bool halt_on_boot;
  87        u32_env core_mask;
  88        u32_env cpu_freq;
  89        u32_env axi_freq;
  90        u32_env tun_freq;
  91        u32_env nvlim;
  92        u32_env icache;
  93        u32_env dcache;
  94        u32_env csm_location;
  95        u32_env l2_cache;
  96        u32_env haps_apb;
  97};
  98
  99/*
 100 * Uncached cross-cpu structure. All CPUs must access to this structure fields
 101 * only with arc_read_uncached_32() / arc_write_uncached_32() accessors (which
 102 * implement ld.di / st.di instructions). Simultaneous cached and uncached
 103 * access to this area will lead to data loss.
 104 * We flush all data caches in board_early_init_r() as we don't want to have
 105 * any dirty line in L1d$ or SL$ in this area.
 106 */
 107struct hsdk_cross_cpu {
 108        /* slave CPU ready flag */
 109        u32 ready_flag;
 110        /* address of the area, which can be used for stack by slave CPU */
 111        u32 stack_ptr;
 112        /* slave CPU status - bootstage number */
 113        s32 status[NR_CPUS];
 114
 115        /*
 116         * Slave CPU data - it is copy of corresponding fields in
 117         * hsdk_env_core_ctl and hsdk_env_common_ctl structures which are
 118         * required for slave CPUs initialization.
 119         * This fields can be populated by copying from hsdk_env_core_ctl
 120         * and hsdk_env_common_ctl structures with sync_cross_cpu_data()
 121         * function.
 122         */
 123        u32 entry[NR_CPUS];
 124        u32 iccm[NR_CPUS];
 125        u32 dccm[NR_CPUS];
 126
 127        u32 core_mask;
 128        u32 icache;
 129        u32 dcache;
 130
 131        u8 cache_padding[ARCH_DMA_MINALIGN];
 132} __aligned(ARCH_DMA_MINALIGN);
 133
 134/* Place for slave CPUs temporary stack */
 135static u32 slave_stack[256 * NR_CPUS] __aligned(ARCH_DMA_MINALIGN);
 136
 137static struct hsdk_env_common_ctl env_common = {};
 138static struct hsdk_env_core_ctl env_core = {};
 139static struct hsdk_cross_cpu cross_cpu_data;
 140
 141static const struct env_map_common env_map_common[] = {
 142        { "core_mask",  ENV_HEX, true,  0x1, 0xF,       &env_common.core_mask },
 143        { "non_volatile_limit", ENV_HEX, true, 0, 0xF,  &env_common.nvlim },
 144        { "icache_ena", ENV_HEX, true,  0, 1,           &env_common.icache },
 145        { "dcache_ena", ENV_HEX, true,  0, 1,           &env_common.dcache },
 146#if defined(CONFIG_BOARD_HSDK_4XD)
 147        { "l2_cache_ena",       ENV_HEX, true,  0, 1,           &env_common.l2_cache },
 148        { "csm_location",       ENV_HEX, true,  0, NO_CCM,      &env_common.csm_location },
 149        { "haps_apb_location",  ENV_HEX, true,  0, 1,           &env_common.haps_apb },
 150#endif /* CONFIG_BOARD_HSDK_4XD */
 151        {}
 152};
 153
 154static const struct env_map_common env_map_clock[] = {
 155        { "cpu_freq",   ENV_DEC, false, 100, 1000,      &env_common.cpu_freq },
 156        { "axi_freq",   ENV_DEC, false, 200, 800,       &env_common.axi_freq },
 157        { "tun_freq",   ENV_DEC, false, 0, 150,         &env_common.tun_freq },
 158        {}
 159};
 160
 161static const struct env_map_percpu env_map_core[] = {
 162        { "core_iccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.iccm },
 163        { "core_dccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.dccm },
 164        {}
 165};
 166
 167static const struct env_map_common env_map_mask[] = {
 168        { "core_mask",  ENV_HEX, false, 0x1, 0xF,       &env_common.core_mask },
 169        {}
 170};
 171
 172static const struct env_map_percpu env_map_go[] = {
 173        { "core_entry", ENV_HEX, true, {0, 0, 0, 0}, {U32_MAX, U32_MAX, U32_MAX, U32_MAX}, &env_core.entry },
 174        {}
 175};
 176
 177enum board_type {
 178        T_BOARD_NONE,
 179        T_BOARD_HSDK,
 180        T_BOARD_HSDK_4XD
 181};
 182
 183static inline enum board_type get_board_type_runtime(void)
 184{
 185        u32 arc_id = read_aux_reg(ARC_AUX_IDENTITY) & 0xFF;
 186
 187        if (arc_id == 0x52)
 188                return T_BOARD_HSDK;
 189        else if (arc_id == 0x54)
 190                return T_BOARD_HSDK_4XD;
 191        else
 192                return T_BOARD_NONE;
 193}
 194
 195static inline enum board_type get_board_type_config(void)
 196{
 197        if (IS_ENABLED(CONFIG_BOARD_HSDK))
 198                return T_BOARD_HSDK;
 199        else if (IS_ENABLED(CONFIG_BOARD_HSDK_4XD))
 200                return T_BOARD_HSDK_4XD;
 201        else
 202                return T_BOARD_NONE;
 203}
 204
 205static bool is_board_match_runtime(enum board_type type_req)
 206{
 207        return get_board_type_runtime() == type_req;
 208}
 209
 210static bool is_board_match_config(enum board_type type_req)
 211{
 212        return get_board_type_config() == type_req;
 213}
 214
 215static const char * board_name(enum board_type type)
 216{
 217        switch (type) {
 218                case T_BOARD_HSDK:
 219                        return "ARC HS Development Kit";
 220                case T_BOARD_HSDK_4XD:
 221                        return "ARC HS4x/HS4xD Development Kit";
 222                default:
 223                        return "?";
 224        }
 225}
 226
 227static bool board_mismatch(void)
 228{
 229        return get_board_type_config() != get_board_type_runtime();
 230}
 231
 232static void sync_cross_cpu_data(void)
 233{
 234        u32 value;
 235
 236        for (u32 i = 0; i < NR_CPUS; i++) {
 237                value = env_core.entry[i].val;
 238                arc_write_uncached_32(&cross_cpu_data.entry[i], value);
 239        }
 240
 241        for (u32 i = 0; i < NR_CPUS; i++) {
 242                value = env_core.iccm[i].val;
 243                arc_write_uncached_32(&cross_cpu_data.iccm[i], value);
 244        }
 245
 246        for (u32 i = 0; i < NR_CPUS; i++) {
 247                value = env_core.dccm[i].val;
 248                arc_write_uncached_32(&cross_cpu_data.dccm[i], value);
 249        }
 250
 251        value = env_common.core_mask.val;
 252        arc_write_uncached_32(&cross_cpu_data.core_mask, value);
 253
 254        value = env_common.icache.val;
 255        arc_write_uncached_32(&cross_cpu_data.icache, value);
 256
 257        value = env_common.dcache.val;
 258        arc_write_uncached_32(&cross_cpu_data.dcache, value);
 259}
 260
 261/* Can be used only on master CPU */
 262static bool is_cpu_used(u32 cpu_id)
 263{
 264        return !!(env_common.core_mask.val & BIT(cpu_id));
 265}
 266
 267/* TODO: add ICCM BCR and DCCM BCR runtime check */
 268static void init_slave_cpu_func(u32 core)
 269{
 270        u32 val;
 271
 272        /* Remap ICCM to another memory region if it exists */
 273        val = arc_read_uncached_32(&cross_cpu_data.iccm[core]);
 274        if (val != NO_CCM)
 275                write_aux_reg(ARC_AUX_ICCM_BASE, val << APERTURE_SHIFT);
 276
 277        /* Remap DCCM to another memory region if it exists */
 278        val = arc_read_uncached_32(&cross_cpu_data.dccm[core]);
 279        if (val != NO_CCM)
 280                write_aux_reg(ARC_AUX_DCCM_BASE, val << APERTURE_SHIFT);
 281
 282        if (arc_read_uncached_32(&cross_cpu_data.icache))
 283                icache_enable();
 284        else
 285                icache_disable();
 286
 287        if (arc_read_uncached_32(&cross_cpu_data.dcache))
 288                dcache_enable();
 289        else
 290                dcache_disable();
 291}
 292
 293static void init_cluster_nvlim(void)
 294{
 295        u32 val = env_common.nvlim.val << APERTURE_SHIFT;
 296
 297        flush_dcache_all();
 298        write_aux_reg(ARC_AUX_NON_VOLATILE_LIMIT, val);
 299        /* AUX_AUX_CACHE_LIMIT reg is missing starting from HS48 */
 300        if (is_board_match_runtime(T_BOARD_HSDK))
 301                write_aux_reg(AUX_AUX_CACHE_LIMIT, val);
 302        flush_n_invalidate_dcache_all();
 303}
 304
 305static void init_cluster_slc(void)
 306{
 307        /* ARC HS38 doesn't support SLC disabling */
 308        if (!is_board_match_config(T_BOARD_HSDK_4XD))
 309                return;
 310
 311        if (env_common.l2_cache.val)
 312                slc_enable();
 313        else
 314                slc_disable();
 315}
 316
 317#define CREG_CSM_BASE           (CREG_BASE + 0x210)
 318
 319static void init_cluster_csm(void)
 320{
 321        /* ARC HS38 in HSDK SoC doesn't include CSM */
 322        if (!is_board_match_config(T_BOARD_HSDK_4XD))
 323                return;
 324
 325        if (env_common.csm_location.val == NO_CCM) {
 326                write_aux_reg(ARC_AUX_CSM_ENABLE, 0);
 327        } else {
 328                /*
 329                 * CSM base address is 256kByte aligned but we allow to map
 330                 * CSM only to aperture start (256MByte aligned)
 331                 * The field in CREG_CSM_BASE is in 17:2 bits itself so we need
 332                 * to shift it.
 333                 */
 334                u32 csm_base = (env_common.csm_location.val * SZ_1K) << 2;
 335
 336                write_aux_reg(ARC_AUX_CSM_ENABLE, 1);
 337                writel(csm_base, (void __iomem *)CREG_CSM_BASE);
 338        }
 339}
 340
 341static void init_master_icache(void)
 342{
 343        if (icache_status()) {
 344                /* I$ is enabled - we need to disable it */
 345                if (!env_common.icache.val)
 346                        icache_disable();
 347        } else {
 348                /* I$ is disabled - we need to enable it */
 349                if (env_common.icache.val) {
 350                        icache_enable();
 351
 352                        /* invalidate I$ right after enable */
 353                        invalidate_icache_all();
 354                }
 355        }
 356}
 357
 358static void init_master_dcache(void)
 359{
 360        if (dcache_status()) {
 361                /* D$ is enabled - we need to disable it */
 362                if (!env_common.dcache.val)
 363                        dcache_disable();
 364        } else {
 365                /* D$ is disabled - we need to enable it */
 366                if (env_common.dcache.val)
 367                        dcache_enable();
 368
 369                /* TODO: probably we need ti invalidate D$ right after enable */
 370        }
 371}
 372
 373static int cleanup_before_go(void)
 374{
 375        disable_interrupts();
 376        sync_n_cleanup_cache_all();
 377
 378        return 0;
 379}
 380
 381void slave_cpu_set_boot_addr(u32 addr)
 382{
 383        /* All cores have reset vector pointing to 0 */
 384        writel(addr, (void __iomem *)RESET_VECTOR_ADDR);
 385
 386        /* Make sure other cores see written value in memory */
 387        sync_n_cleanup_cache_all();
 388}
 389
 390static inline void halt_this_cpu(void)
 391{
 392        __builtin_arc_flag(1);
 393}
 394
 395static u32 get_masked_cpu_ctart_reg(void)
 396{
 397        int cmd = readl((void __iomem *)CREG_CPU_START);
 398
 399        /*
 400         * Quirk for HSDK-4xD - due to HW issues HSDK can use any pulse polarity
 401         * and HSDK-4xD require active low polarity of cpu_start pulse.
 402         */
 403        cmd &= ~CREG_CPU_START_POL;
 404
 405        cmd &= ~CREG_CPU_START_MASK;
 406
 407        return cmd;
 408}
 409
 410static void smp_kick_cpu_x(u32 cpu_id)
 411{
 412        int cmd;
 413
 414        if (cpu_id > NR_CPUS)
 415                return;
 416
 417        cmd = get_masked_cpu_ctart_reg();
 418        cmd |= (1 << cpu_id);
 419        writel(cmd, (void __iomem *)CREG_CPU_START);
 420}
 421
 422static u32 prepare_cpu_ctart_reg(void)
 423{
 424        return get_masked_cpu_ctart_reg() | env_common.core_mask.val;
 425}
 426
 427/* slave CPU entry for configuration */
 428__attribute__((naked, noreturn, flatten)) noinline void hsdk_core_init_f(void)
 429{
 430        __asm__ __volatile__(
 431                "ld.di  r8,     [%0]\n"
 432                "mov    %%sp,   r8\n"
 433                "mov    %%fp,   %%sp\n"
 434                : /* no output */
 435                : "r" (&cross_cpu_data.stack_ptr));
 436
 437        invalidate_icache_all();
 438
 439        arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_1);
 440        init_slave_cpu_func(CPU_ID_GET());
 441
 442        arc_write_uncached_32(&cross_cpu_data.ready_flag, SLAVE_CPU_READY);
 443        arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_2);
 444
 445        /* Halt the processor until the master kick us again */
 446        halt_this_cpu();
 447
 448        /*
 449         * 3 NOPs after FLAG 1 instruction are no longer required for ARCv2
 450         * cores but we leave them for gebug purposes.
 451         */
 452        __builtin_arc_nop();
 453        __builtin_arc_nop();
 454        __builtin_arc_nop();
 455
 456        arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_3);
 457
 458        /* get the updated entry - invalidate i$ */
 459        invalidate_icache_all();
 460
 461        arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_4);
 462
 463        /* Run our program */
 464        ((void (*)(void))(arc_read_uncached_32(&cross_cpu_data.entry[CPU_ID_GET()])))();
 465
 466        /* This bootstage is unreachable as we don't return from app we launch */
 467        arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_5);
 468
 469        /* Something went terribly wrong */
 470        while (true)
 471                halt_this_cpu();
 472}
 473
 474static void clear_cross_cpu_data(void)
 475{
 476        arc_write_uncached_32(&cross_cpu_data.ready_flag, 0);
 477        arc_write_uncached_32(&cross_cpu_data.stack_ptr, 0);
 478
 479        for (u32 i = 0; i < NR_CPUS; i++)
 480                arc_write_uncached_32(&cross_cpu_data.status[i], 0);
 481}
 482
 483static noinline void do_init_slave_cpu(u32 cpu_id)
 484{
 485        /* attempts number for check clave CPU ready_flag */
 486        u32 attempts = 100;
 487        u32 stack_ptr = (u32)(slave_stack + (64 * cpu_id));
 488
 489        if (cpu_id >= NR_CPUS)
 490                return;
 491
 492        arc_write_uncached_32(&cross_cpu_data.ready_flag, 0);
 493
 494        /* Use global unique place for each slave cpu stack */
 495        arc_write_uncached_32(&cross_cpu_data.stack_ptr, stack_ptr);
 496
 497        debug("CPU %u: stack pool base: %p\n", cpu_id, slave_stack);
 498        debug("CPU %u: current slave stack base: %x\n", cpu_id, stack_ptr);
 499        slave_cpu_set_boot_addr((u32)hsdk_core_init_f);
 500
 501        smp_kick_cpu_x(cpu_id);
 502
 503        debug("CPU %u: cross-cpu flag: %x [before timeout]\n", cpu_id,
 504              arc_read_uncached_32(&cross_cpu_data.ready_flag));
 505
 506        while (!arc_read_uncached_32(&cross_cpu_data.ready_flag) && attempts--)
 507                mdelay(10);
 508
 509        /* Just to be sure that slave cpu is halted after it set ready_flag */
 510        mdelay(20);
 511
 512        /*
 513         * Only print error here if we reach timeout as there is no option to
 514         * halt slave cpu (or check that slave cpu is halted)
 515         */
 516        if (!attempts)
 517                pr_err("CPU %u is not responding after init!\n", cpu_id);
 518
 519        /* Check current stage of slave cpu */
 520        if (arc_read_uncached_32(&cross_cpu_data.status[cpu_id]) != BOOTSTAGE_2)
 521                pr_err("CPU %u status is unexpected: %d\n", cpu_id,
 522                       arc_read_uncached_32(&cross_cpu_data.status[cpu_id]));
 523
 524        debug("CPU %u: cross-cpu flag: %x [after timeout]\n", cpu_id,
 525              arc_read_uncached_32(&cross_cpu_data.ready_flag));
 526        debug("CPU %u: status: %d [after timeout]\n", cpu_id,
 527              arc_read_uncached_32(&cross_cpu_data.status[cpu_id]));
 528}
 529
 530static void do_init_slave_cpus(void)
 531{
 532        clear_cross_cpu_data();
 533        sync_cross_cpu_data();
 534
 535        debug("cross_cpu_data location: %#x\n", (u32)&cross_cpu_data);
 536
 537        for (u32 i = MASTER_CPU_ID + 1; i < NR_CPUS; i++)
 538                if (is_cpu_used(i))
 539                        do_init_slave_cpu(i);
 540}
 541
 542static void do_init_master_cpu(void)
 543{
 544        /*
 545         * Setup master caches even if master isn't used as we want to use
 546         * same cache configuration on all running CPUs
 547         */
 548        init_master_icache();
 549        init_master_dcache();
 550}
 551
 552enum hsdk_axi_masters {
 553        M_HS_CORE = 0,
 554        M_HS_RTT,
 555        M_AXI_TUN,
 556        M_HDMI_VIDEO,
 557        M_HDMI_AUDIO,
 558        M_USB_HOST,
 559        M_ETHERNET,
 560        M_SDIO,
 561        M_GPU,
 562        M_DMAC_0,
 563        M_DMAC_1,
 564        M_DVFS
 565};
 566
 567#define UPDATE_VAL      1
 568
 569/*
 570 * m    master          AXI_M_m_SLV0    AXI_M_m_SLV1    AXI_M_m_OFFSET0 AXI_M_m_OFFSET1
 571 * 0    HS (CBU)        0x11111111      0x63111111      0xFEDCBA98      0x0E543210
 572 * 1    HS (RTT)        0x77777777      0x77777777      0xFEDCBA98      0x76543210
 573 * 2    AXI Tunnel      0x88888888      0x88888888      0xFEDCBA98      0x76543210
 574 * 3    HDMI-VIDEO      0x77777777      0x77777777      0xFEDCBA98      0x76543210
 575 * 4    HDMI-ADUIO      0x77777777      0x77777777      0xFEDCBA98      0x76543210
 576 * 5    USB-HOST        0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
 577 * 6    ETHERNET        0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
 578 * 7    SDIO            0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
 579 * 8    GPU             0x77777777      0x77777777      0xFEDCBA98      0x76543210
 580 * 9    DMAC (port #1)  0x77777777      0x77777777      0xFEDCBA98      0x76543210
 581 * 10   DMAC (port #2)  0x77777777      0x77777777      0xFEDCBA98      0x76543210
 582 * 11   DVFS            0x00000000      0x60000000      0x00000000      0x00000000
 583 *
 584 * Please read ARC HS Development IC Specification, section 17.2 for more
 585 * information about apertures configuration.
 586 * NOTE: we intentionally modify default settings in U-boot. Default settings
 587 * are specified in "Table 111 CREG Address Decoder register reset values".
 588 */
 589
 590#define CREG_AXI_M_SLV0(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m)))
 591#define CREG_AXI_M_SLV1(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x004))
 592#define CREG_AXI_M_OFT0(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x008))
 593#define CREG_AXI_M_OFT1(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x00C))
 594#define CREG_AXI_M_UPDT(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x014))
 595
 596#define CREG_AXI_M_HS_CORE_BOOT ((void __iomem *)(CREG_BASE + 0x010))
 597
 598#define CREG_PAE        ((void __iomem *)(CREG_BASE + 0x180))
 599#define CREG_PAE_UPDT   ((void __iomem *)(CREG_BASE + 0x194))
 600
 601void init_memory_bridge(void)
 602{
 603        u32 reg;
 604
 605        /*
 606         * M_HS_CORE has one unic register - BOOT.
 607         * We need to clean boot mirror (BOOT[1:0]) bits in them.
 608         */
 609        reg = readl(CREG_AXI_M_HS_CORE_BOOT) & (~0x3);
 610        writel(reg, CREG_AXI_M_HS_CORE_BOOT);
 611        writel(0x11111111, CREG_AXI_M_SLV0(M_HS_CORE));
 612        writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE));
 613        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_CORE));
 614        writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE));
 615        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE));
 616
 617        writel(0x77777777, CREG_AXI_M_SLV0(M_HS_RTT));
 618        writel(0x77777777, CREG_AXI_M_SLV1(M_HS_RTT));
 619        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_RTT));
 620        writel(0x76543210, CREG_AXI_M_OFT1(M_HS_RTT));
 621        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_RTT));
 622
 623        writel(0x88888888, CREG_AXI_M_SLV0(M_AXI_TUN));
 624        writel(0x88888888, CREG_AXI_M_SLV1(M_AXI_TUN));
 625        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_AXI_TUN));
 626        writel(0x76543210, CREG_AXI_M_OFT1(M_AXI_TUN));
 627        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_AXI_TUN));
 628
 629        writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_VIDEO));
 630        writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_VIDEO));
 631        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_VIDEO));
 632        writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_VIDEO));
 633        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_VIDEO));
 634
 635        writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_AUDIO));
 636        writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_AUDIO));
 637        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_AUDIO));
 638        writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_AUDIO));
 639        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_AUDIO));
 640
 641        writel(0x77777777, CREG_AXI_M_SLV0(M_USB_HOST));
 642        writel(0x77999999, CREG_AXI_M_SLV1(M_USB_HOST));
 643        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_USB_HOST));
 644        writel(0x76DCBA98, CREG_AXI_M_OFT1(M_USB_HOST));
 645        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST));
 646
 647        writel(0x77777777, CREG_AXI_M_SLV0(M_ETHERNET));
 648        writel(0x77999999, CREG_AXI_M_SLV1(M_ETHERNET));
 649        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_ETHERNET));
 650        writel(0x76DCBA98, CREG_AXI_M_OFT1(M_ETHERNET));
 651        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET));
 652
 653        writel(0x77777777, CREG_AXI_M_SLV0(M_SDIO));
 654        writel(0x77999999, CREG_AXI_M_SLV1(M_SDIO));
 655        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_SDIO));
 656        writel(0x76DCBA98, CREG_AXI_M_OFT1(M_SDIO));
 657        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO));
 658
 659        writel(0x77777777, CREG_AXI_M_SLV0(M_GPU));
 660        writel(0x77777777, CREG_AXI_M_SLV1(M_GPU));
 661        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_GPU));
 662        writel(0x76543210, CREG_AXI_M_OFT1(M_GPU));
 663        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU));
 664
 665        writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
 666        writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0));
 667        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
 668        writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0));
 669        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
 670
 671        writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
 672        writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1));
 673        writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
 674        writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1));
 675        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
 676
 677        writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS));
 678        writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS));
 679        writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS));
 680        writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS));
 681        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS));
 682
 683        writel(0x00000000, CREG_PAE);
 684        writel(UPDATE_VAL, CREG_PAE_UPDT);
 685}
 686
 687/*
 688 * For HSDK-4xD we do additional AXI bridge tweaking in hsdk_init command:
 689 * - we shrink IOC region.
 690 * - we configure HS CORE SLV1 aperture depending on haps_apb_location
 691 *   environment variable.
 692 *
 693 * As we've already configured AXI bridge in init_memory_bridge we don't
 694 * do full configuration here but reconfigure changed part.
 695 *
 696 * m    master          AXI_M_m_SLV0    AXI_M_m_SLV1    AXI_M_m_OFFSET0 AXI_M_m_OFFSET1
 697 * 0    HS (CBU)        0x11111111      0x63111111      0xFEDCBA98      0x0E543210      [haps_apb_location = 0]
 698 * 0    HS (CBU)        0x11111111      0x61111111      0xFEDCBA98      0x06543210      [haps_apb_location = 1]
 699 * 1    HS (RTT)        0x77777777      0x77777777      0xFEDCBA98      0x76543210
 700 * 2    AXI Tunnel      0x88888888      0x88888888      0xFEDCBA98      0x76543210
 701 * 3    HDMI-VIDEO      0x77777777      0x77777777      0xFEDCBA98      0x76543210
 702 * 4    HDMI-ADUIO      0x77777777      0x77777777      0xFEDCBA98      0x76543210
 703 * 5    USB-HOST        0x77777777      0x77779999      0xFEDCBA98      0x7654BA98
 704 * 6    ETHERNET        0x77777777      0x77779999      0xFEDCBA98      0x7654BA98
 705 * 7    SDIO            0x77777777      0x77779999      0xFEDCBA98      0x7654BA98
 706 * 8    GPU             0x77777777      0x77777777      0xFEDCBA98      0x76543210
 707 * 9    DMAC (port #1)  0x77777777      0x77777777      0xFEDCBA98      0x76543210
 708 * 10   DMAC (port #2)  0x77777777      0x77777777      0xFEDCBA98      0x76543210
 709 * 11   DVFS            0x00000000      0x60000000      0x00000000      0x00000000
 710 */
 711void tweak_memory_bridge_cfg(void)
 712{
 713        /*
 714         * Only HSDK-4xD requre additional AXI bridge tweaking depending on
 715         * haps_apb_location environment variable
 716         */
 717        if (!is_board_match_config(T_BOARD_HSDK_4XD))
 718                return;
 719
 720        if (env_common.haps_apb.val) {
 721                writel(0x61111111, CREG_AXI_M_SLV1(M_HS_CORE));
 722                writel(0x06543210, CREG_AXI_M_OFT1(M_HS_CORE));
 723        } else {
 724                writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE));
 725                writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE));
 726        }
 727        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE));
 728
 729        writel(0x77779999, CREG_AXI_M_SLV1(M_USB_HOST));
 730        writel(0x7654BA98, CREG_AXI_M_OFT1(M_USB_HOST));
 731        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST));
 732
 733        writel(0x77779999, CREG_AXI_M_SLV1(M_ETHERNET));;
 734        writel(0x7654BA98, CREG_AXI_M_OFT1(M_ETHERNET));
 735        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET));
 736
 737        writel(0x77779999, CREG_AXI_M_SLV1(M_SDIO));
 738        writel(0x7654BA98, CREG_AXI_M_OFT1(M_SDIO));
 739        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO));
 740}
 741
 742static void setup_clocks(void)
 743{
 744        ulong rate;
 745
 746        /* Setup CPU clock */
 747        if (env_common.cpu_freq.set) {
 748                rate = env_common.cpu_freq.val;
 749                soc_clk_ctl("cpu-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ);
 750        }
 751
 752        /* Setup TUN clock */
 753        if (env_common.tun_freq.set) {
 754                rate = env_common.tun_freq.val;
 755                if (rate)
 756                        soc_clk_ctl("tun-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ);
 757                else
 758                        soc_clk_ctl("tun-clk", NULL, CLK_OFF);
 759        }
 760
 761        if (env_common.axi_freq.set) {
 762                rate = env_common.axi_freq.val;
 763                soc_clk_ctl("axi-clk", &rate, CLK_SET | CLK_ON | CLK_MHZ);
 764        }
 765}
 766
 767static void do_init_cluster(void)
 768{
 769        /*
 770         * A multi-core ARC HS configuration always includes only one
 771         * ARC_AUX_NON_VOLATILE_LIMIT register, which is shared by all the
 772         * cores.
 773         */
 774        init_cluster_nvlim();
 775        init_cluster_csm();
 776        init_cluster_slc();
 777        tweak_memory_bridge_cfg();
 778}
 779
 780static int check_master_cpu_id(void)
 781{
 782        if (CPU_ID_GET() == MASTER_CPU_ID)
 783                return 0;
 784
 785        pr_err("u-boot runs on non-master cpu with id: %lu\n", CPU_ID_GET());
 786
 787        return -ENOENT;
 788}
 789
 790static noinline int prepare_cpus(void)
 791{
 792        int ret;
 793
 794        ret = check_master_cpu_id();
 795        if (ret)
 796                return ret;
 797
 798        ret = envs_process_and_validate(env_map_common, env_map_core, is_cpu_used);
 799        if (ret)
 800                return ret;
 801
 802        printf("CPU start mask is %#x\n", env_common.core_mask.val);
 803
 804        do_init_slave_cpus();
 805        do_init_master_cpu();
 806        do_init_cluster();
 807
 808        return 0;
 809}
 810
 811static int hsdk_go_run(u32 cpu_start_reg)
 812{
 813        /* Cleanup caches, disable interrupts */
 814        cleanup_before_go();
 815
 816        if (env_common.halt_on_boot)
 817                halt_this_cpu();
 818
 819        /*
 820         * 3 NOPs after FLAG 1 instruction are no longer required for ARCv2
 821         * cores but we leave them for gebug purposes.
 822         */
 823        __builtin_arc_nop();
 824        __builtin_arc_nop();
 825        __builtin_arc_nop();
 826
 827        /* Kick chosen slave CPUs */
 828        writel(cpu_start_reg, (void __iomem *)CREG_CPU_START);
 829
 830        if (is_cpu_used(MASTER_CPU_ID))
 831                ((void (*)(void))(env_core.entry[MASTER_CPU_ID].val))();
 832        else
 833                halt_this_cpu();
 834
 835        pr_err("u-boot still runs on cpu [%ld]\n", CPU_ID_GET());
 836
 837        /*
 838         * We will never return after executing our program if master cpu used
 839         * otherwise halt master cpu manually.
 840         */
 841        while (true)
 842                halt_this_cpu();
 843
 844        return 0;
 845}
 846
 847int board_prep_linux(bootm_headers_t *images)
 848{
 849        int ret, ofst;
 850        char mask[15];
 851
 852        ret = envs_read_validate_common(env_map_mask);
 853        if (ret)
 854                return ret;
 855
 856        /* Rollback to default values */
 857        if (!env_common.core_mask.set) {
 858                env_common.core_mask.val = ALL_CPU_MASK;
 859                env_common.core_mask.set = true;
 860        }
 861
 862        printf("CPU start mask is %#x\n", env_common.core_mask.val);
 863
 864        if (!is_cpu_used(MASTER_CPU_ID))
 865                pr_err("ERR: try to launch linux with CPU[0] disabled! It doesn't work for ARC.\n");
 866
 867        /*
 868         * If we want to launch linux on all CPUs we don't need to patch
 869         * linux DTB as it is default configuration
 870         */
 871        if (env_common.core_mask.val == ALL_CPU_MASK)
 872                return 0;
 873
 874        if (!CONFIG_IS_ENABLED(OF_LIBFDT) || !images->ft_len) {
 875                pr_err("WARN: core_mask setup will work properly only with external DTB!\n");
 876                return 0;
 877        }
 878
 879        /* patch '/possible-cpus' property according to cpu mask */
 880        ofst = fdt_path_offset(images->ft_addr, "/");
 881        sprintf(mask, "%s%s%s%s",
 882                is_cpu_used(0) ? "0," : "",
 883                is_cpu_used(1) ? "1," : "",
 884                is_cpu_used(2) ? "2," : "",
 885                is_cpu_used(3) ? "3," : "");
 886        ret = fdt_setprop_string(images->ft_addr, ofst, "possible-cpus", mask);
 887        /*
 888         * If we failed to patch '/possible-cpus' property we don't need break
 889         * linux loading process: kernel will handle it but linux will print
 890         * warning like "Timeout: CPU1 FAILED to comeup !!!".
 891         * So warn here about error, but return 0 like no error had occurred.
 892         */
 893        if (ret)
 894                pr_err("WARN: failed to patch '/possible-cpus' property, ret=%d\n",
 895                       ret);
 896
 897        return 0;
 898}
 899
 900void board_jump_and_run(ulong entry, int zero, int arch, uint params)
 901{
 902        void (*kernel_entry)(int zero, int arch, uint params);
 903        u32 cpu_start_reg;
 904
 905        kernel_entry = (void (*)(int, int, uint))entry;
 906
 907        /* Prepare CREG_CPU_START for kicking chosen CPUs */
 908        cpu_start_reg = prepare_cpu_ctart_reg();
 909
 910        /* In case of run without hsdk_init */
 911        slave_cpu_set_boot_addr(entry);
 912
 913        /* In case of run with hsdk_init */
 914        for (u32 i = 0; i < NR_CPUS; i++) {
 915                env_core.entry[i].val = entry;
 916                env_core.entry[i].set = true;
 917        }
 918        /* sync cross_cpu struct as we updated core-entry variables */
 919        sync_cross_cpu_data();
 920
 921        /* Kick chosen slave CPUs */
 922        writel(cpu_start_reg, (void __iomem *)CREG_CPU_START);
 923
 924        if (is_cpu_used(0))
 925                kernel_entry(zero, arch, params);
 926}
 927
 928static int hsdk_go_prepare_and_run(void)
 929{
 930        /* Prepare CREG_CPU_START for kicking chosen CPUs */
 931        u32 reg = prepare_cpu_ctart_reg();
 932
 933        if (env_common.halt_on_boot)
 934                printf("CPU will halt before application start, start application with debugger.\n");
 935
 936        return hsdk_go_run(reg);
 937}
 938
 939static int do_hsdk_go(struct cmd_tbl *cmdtp, int flag, int argc,
 940                      char *const argv[])
 941{
 942        int ret;
 943
 944        if (board_mismatch()) {
 945                printf("ERR: U-boot is not configured for this board!\n");
 946                return CMD_RET_FAILURE;
 947        }
 948
 949        /*
 950         * Check for 'halt' parameter. 'halt' = enter halt-mode just before
 951         * starting the application; can be used for debug.
 952         */
 953        if (argc > 1) {
 954                env_common.halt_on_boot = !strcmp(argv[1], "halt");
 955                if (!env_common.halt_on_boot) {
 956                        pr_err("Unrecognised parameter: \'%s\'\n", argv[1]);
 957                        return CMD_RET_FAILURE;
 958                }
 959        }
 960
 961        ret = check_master_cpu_id();
 962        if (ret)
 963                return ret;
 964
 965        ret = envs_process_and_validate(env_map_mask, env_map_go, is_cpu_used);
 966        if (ret)
 967                return ret;
 968
 969        /* sync cross_cpu struct as we updated core-entry variables */
 970        sync_cross_cpu_data();
 971
 972        ret = hsdk_go_prepare_and_run();
 973
 974        return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
 975}
 976
 977U_BOOT_CMD(
 978        hsdk_go, 3, 0, do_hsdk_go,
 979        "Synopsys HSDK specific command",
 980        "     - Boot stand-alone application on HSDK\n"
 981        "hsdk_go halt - Boot stand-alone application on HSDK, halt CPU just before application run\n"
 982);
 983
 984/*
 985 * We may simply use static variable here to store init status, but we also want
 986 * to avoid the situation when we reload U-boot via MDB after previous
 987 * init is done but HW reset (board reset) isn't done. So let's store the
 988 * init status in any unused register (i.e CREG_CPU_0_ENTRY) so status will
 989 * survive after U-boot is reloaded via MDB.
 990 */
 991#define INIT_MARKER_REGISTER            ((void __iomem *)CREG_CPU_0_ENTRY)
 992/* must be equal to INIT_MARKER_REGISTER reset value */
 993#define INIT_MARKER_PENDING             0
 994
 995static bool init_marker_get(void)
 996{
 997        return readl(INIT_MARKER_REGISTER) != INIT_MARKER_PENDING;
 998}
 999
1000static void init_mark_done(void)
1001{
1002        writel(~INIT_MARKER_PENDING, INIT_MARKER_REGISTER);
1003}
1004
1005static int do_hsdk_init(struct cmd_tbl *cmdtp, int flag, int argc,
1006                        char *const argv[])
1007{
1008        int ret;
1009
1010        if (board_mismatch()) {
1011                printf("ERR: U-boot is not configured for this board!\n");
1012                return CMD_RET_FAILURE;
1013        }
1014
1015        /* hsdk_init can be run only once */
1016        if (init_marker_get()) {
1017                printf("HSDK HW is already initialized! Please reset the board if you want to change the configuration.\n");
1018                return CMD_RET_FAILURE;
1019        }
1020
1021        ret = prepare_cpus();
1022        if (!ret)
1023                init_mark_done();
1024
1025        return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
1026}
1027
1028U_BOOT_CMD(
1029        hsdk_init, 1, 0, do_hsdk_init,
1030        "Synopsys HSDK specific command",
1031        "- Init HSDK HW\n"
1032);
1033
1034static int do_hsdk_clock_set(struct cmd_tbl *cmdtp, int flag, int argc,
1035                             char *const argv[])
1036{
1037        int ret = 0;
1038
1039        /* Strip off leading subcommand argument */
1040        argc--;
1041        argv++;
1042
1043        envs_cleanup_common(env_map_clock);
1044
1045        if (!argc) {
1046                printf("Set clocks to values specified in environment\n");
1047                ret = envs_read_common(env_map_clock);
1048        } else {
1049                printf("Set clocks to values specified in args\n");
1050                ret = args_envs_enumerate(env_map_clock, 2, argc, argv);
1051        }
1052
1053        if (ret)
1054                return CMD_RET_FAILURE;
1055
1056        ret = envs_validate_common(env_map_clock);
1057        if (ret)
1058                return CMD_RET_FAILURE;
1059
1060        /* Setup clock tree HW */
1061        setup_clocks();
1062
1063        return CMD_RET_SUCCESS;
1064}
1065
1066static int do_hsdk_clock_get(struct cmd_tbl *cmdtp, int flag, int argc,
1067                             char *const argv[])
1068{
1069        ulong rate;
1070
1071        if (soc_clk_ctl("cpu-clk", &rate, CLK_GET | CLK_MHZ))
1072                return CMD_RET_FAILURE;
1073
1074        if (env_set_ulong("cpu_freq", rate))
1075                return CMD_RET_FAILURE;
1076
1077        if (soc_clk_ctl("tun-clk", &rate, CLK_GET | CLK_MHZ))
1078                return CMD_RET_FAILURE;
1079
1080        if (env_set_ulong("tun_freq", rate))
1081                return CMD_RET_FAILURE;
1082
1083        if (soc_clk_ctl("axi-clk", &rate, CLK_GET | CLK_MHZ))
1084                return CMD_RET_FAILURE;
1085
1086        if (env_set_ulong("axi_freq", rate))
1087                return CMD_RET_FAILURE;
1088
1089        printf("Clock values are saved to environment\n");
1090
1091        return CMD_RET_SUCCESS;
1092}
1093
1094static int do_hsdk_clock_print(struct cmd_tbl *cmdtp, int flag, int argc,
1095                               char *const argv[])
1096{
1097        /* Main clocks */
1098        soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ);
1099        soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
1100        soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ);
1101        soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ);
1102
1103        return CMD_RET_SUCCESS;
1104}
1105
1106static int do_hsdk_clock_print_all(struct cmd_tbl *cmdtp, int flag, int argc,
1107                                   char *const argv[])
1108{
1109        /*
1110         * NOTE: as of today we don't use some peripherals like HDMI / EBI
1111         * so we don't want to print their clocks ("hdmi-sys-clk", "hdmi-pll",
1112         * "hdmi-clk", "ebi-clk"). Nevertheless their clock subsystems is fully
1113         * functional and we can print their clocks if it is required
1114         */
1115
1116        /* CPU clock domain */
1117        soc_clk_ctl("cpu-pll", NULL, CLK_PRINT | CLK_MHZ);
1118        soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ);
1119        printf("\n");
1120
1121        /* SYS clock domain */
1122        soc_clk_ctl("sys-pll", NULL, CLK_PRINT | CLK_MHZ);
1123        soc_clk_ctl("apb-clk", NULL, CLK_PRINT | CLK_MHZ);
1124        soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ);
1125        soc_clk_ctl("eth-clk", NULL, CLK_PRINT | CLK_MHZ);
1126        soc_clk_ctl("usb-clk", NULL, CLK_PRINT | CLK_MHZ);
1127        soc_clk_ctl("sdio-clk", NULL, CLK_PRINT | CLK_MHZ);
1128        if (is_board_match_runtime(T_BOARD_HSDK_4XD))
1129                soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ);
1130        soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ);
1131        if (is_board_match_runtime(T_BOARD_HSDK)) {
1132                soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ);
1133                soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
1134        }
1135        soc_clk_ctl("dmac-core-clk", NULL, CLK_PRINT | CLK_MHZ);
1136        soc_clk_ctl("dmac-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
1137        soc_clk_ctl("sdio-ref-clk", NULL, CLK_PRINT | CLK_MHZ);
1138        soc_clk_ctl("spi-clk", NULL, CLK_PRINT | CLK_MHZ);
1139        soc_clk_ctl("i2c-clk", NULL, CLK_PRINT | CLK_MHZ);
1140/*      soc_clk_ctl("ebi-clk", NULL, CLK_PRINT | CLK_MHZ); */
1141        soc_clk_ctl("uart-clk", NULL, CLK_PRINT | CLK_MHZ);
1142        printf("\n");
1143
1144        /* DDR clock domain */
1145        soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ);
1146        printf("\n");
1147
1148        /* HDMI clock domain */
1149        if (is_board_match_runtime(T_BOARD_HSDK_4XD)) {
1150                soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ);
1151                soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ);
1152                printf("\n");
1153        }
1154
1155        /* TUN clock domain */
1156        soc_clk_ctl("tun-pll", NULL, CLK_PRINT | CLK_MHZ);
1157        soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
1158        soc_clk_ctl("rom-clk", NULL, CLK_PRINT | CLK_MHZ);
1159        soc_clk_ctl("pwm-clk", NULL, CLK_PRINT | CLK_MHZ);
1160        if (is_board_match_runtime(T_BOARD_HSDK_4XD))
1161                soc_clk_ctl("timer-clk", NULL, CLK_PRINT | CLK_MHZ);
1162        printf("\n");
1163
1164        return CMD_RET_SUCCESS;
1165}
1166
1167struct cmd_tbl cmd_hsdk_clock[] = {
1168        U_BOOT_CMD_MKENT(set, 3, 0, do_hsdk_clock_set, "", ""),
1169        U_BOOT_CMD_MKENT(get, 3, 0, do_hsdk_clock_get, "", ""),
1170        U_BOOT_CMD_MKENT(print, 4, 0, do_hsdk_clock_print, "", ""),
1171        U_BOOT_CMD_MKENT(print_all, 4, 0, do_hsdk_clock_print_all, "", ""),
1172};
1173
1174static int do_hsdk_clock(struct cmd_tbl *cmdtp, int flag, int argc,
1175                         char *const argv[])
1176{
1177        struct cmd_tbl *c;
1178
1179        if (argc < 2)
1180                return CMD_RET_USAGE;
1181
1182        /* Strip off leading 'hsdk_clock' command argument */
1183        argc--;
1184        argv++;
1185
1186        c = find_cmd_tbl(argv[0], cmd_hsdk_clock, ARRAY_SIZE(cmd_hsdk_clock));
1187        if (!c)
1188                return CMD_RET_USAGE;
1189
1190        return c->cmd(cmdtp, flag, argc, argv);
1191}
1192
1193U_BOOT_CMD(
1194        hsdk_clock, CONFIG_SYS_MAXARGS, 0, do_hsdk_clock,
1195        "Synopsys HSDK specific clock command",
1196        "set   - Set clock to values specified in environment / command line arguments\n"
1197        "hsdk_clock get   - Save clock values to environment\n"
1198        "hsdk_clock print - Print main clock values to console\n"
1199        "hsdk_clock print_all - Print all clock values to console\n"
1200);
1201
1202/* init calls */
1203int board_early_init_f(void)
1204{
1205        /*
1206         * Setup AXI apertures unconditionally as we want to have DDR
1207         * in 0x00000000 region when we are kicking slave cpus.
1208         */
1209        init_memory_bridge();
1210
1211        /*
1212         * Switch SDIO external ciu clock divider from default div-by-8 to
1213         * minimum possible div-by-2.
1214         */
1215        writel(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *)SDIO_UHS_REG_EXT);
1216
1217        return 0;
1218}
1219
1220int board_early_init_r(void)
1221{
1222        /*
1223         * TODO: Init USB here to be able read environment from USB MSD.
1224         * It can be done with usb_init() call. We can't do it right now
1225         * due to brocken USB IP SW reset and lack of USB IP HW reset in
1226         * linux kernel (if we init USB here we will break USB in linux)
1227         */
1228
1229        /*
1230         * Flush all d$ as we want to use uncached area with st.di / ld.di
1231         * instructions and we don't want to have any dirty line in L1d$ or SL$
1232         * in this area. It is enough to flush all d$ once here as we access to
1233         * uncached area with regular st (non .di) instruction only when we copy
1234         * data during u-boot relocation.
1235         */
1236        flush_dcache_all();
1237
1238        printf("Relocation Offset is: %08lx\n", gd->reloc_off);
1239
1240        return 0;
1241}
1242
1243int board_late_init(void)
1244{
1245        /*
1246         * Populate environment with clock frequency values -
1247         * run hsdk_clock get callback without uboot command run.
1248         */
1249        do_hsdk_clock_get(NULL, 0, 0, NULL);
1250
1251        return 0;
1252}
1253
1254int checkboard(void)
1255{
1256        u32 reg;
1257
1258        printf("Board: Synopsys %s\n", board_name(get_board_type_runtime()));
1259
1260        if (board_mismatch())
1261                printf("WARN: U-boot is configured NOT for this board but for %s!\n",
1262                       board_name(get_board_type_config()));
1263
1264        reg = readl(CREG_AXI_M_HS_CORE_BOOT) & CREG_CORE_BOOT_IMAGE;
1265        printf("U-boot autostart: %s\n", reg ? "enabled" : "disabled");
1266
1267        return 0;
1268};
1269