uboot/arch/arm/mach-socfpga/misc_gen5.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2012-2017 Altera Corporation <www.altera.com>
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <asm/io.h>
   9#include <errno.h>
  10#include <fdtdec.h>
  11#include <linux/libfdt.h>
  12#include <altera.h>
  13#include <miiphy.h>
  14#include <netdev.h>
  15#include <watchdog.h>
  16#include <asm/arch/misc.h>
  17#include <asm/arch/reset_manager.h>
  18#include <asm/arch/scan_manager.h>
  19#include <asm/arch/sdram.h>
  20#include <asm/arch/system_manager.h>
  21#include <asm/arch/nic301.h>
  22#include <asm/arch/scu.h>
  23#include <asm/pl310.h>
  24
  25#include <dt-bindings/reset/altr,rst-mgr.h>
  26
  27DECLARE_GLOBAL_DATA_PTR;
  28
  29static struct pl310_regs *const pl310 =
  30        (struct pl310_regs *)CONFIG_SYS_PL310_BASE;
  31static struct socfpga_system_manager *sysmgr_regs =
  32        (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
  33static struct nic301_registers *nic301_regs =
  34        (struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS;
  35static struct scu_registers *scu_regs =
  36        (struct scu_registers *)SOCFPGA_MPUSCU_ADDRESS;
  37
  38/*
  39 * DesignWare Ethernet initialization
  40 */
  41#ifdef CONFIG_ETH_DESIGNWARE
  42void dwmac_deassert_reset(const unsigned int of_reset_id,
  43                                 const u32 phymode)
  44{
  45        u32 physhift, reset;
  46
  47        if (of_reset_id == EMAC0_RESET) {
  48                physhift = SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB;
  49                reset = SOCFPGA_RESET(EMAC0);
  50        } else if (of_reset_id == EMAC1_RESET) {
  51                physhift = SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB;
  52                reset = SOCFPGA_RESET(EMAC1);
  53        } else {
  54                printf("GMAC: Invalid reset ID (%i)!\n", of_reset_id);
  55                return;
  56        }
  57
  58        /* configure to PHY interface select choosed */
  59        clrsetbits_le32(&sysmgr_regs->emacgrp_ctrl,
  60                        SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << physhift,
  61                        phymode << physhift);
  62
  63        /* Release the EMAC controller from reset */
  64        socfpga_per_reset(reset, 0);
  65}
  66
  67static u32 dwmac_phymode_to_modereg(const char *phymode, u32 *modereg)
  68{
  69        if (!phymode)
  70                return -EINVAL;
  71
  72        if (!strcmp(phymode, "mii") || !strcmp(phymode, "gmii")) {
  73                *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
  74                return 0;
  75        }
  76
  77        if (!strcmp(phymode, "rgmii")) {
  78                *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
  79                return 0;
  80        }
  81
  82        if (!strcmp(phymode, "rmii")) {
  83                *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII;
  84                return 0;
  85        }
  86
  87        return -EINVAL;
  88}
  89
  90static int socfpga_eth_reset(void)
  91{
  92        const void *fdt = gd->fdt_blob;
  93        struct fdtdec_phandle_args args;
  94        const char *phy_mode;
  95        u32 phy_modereg;
  96        int nodes[2];   /* Max. two GMACs */
  97        int ret, count;
  98        int i, node;
  99
 100        /* Put both GMACs into RESET state. */
 101        socfpga_per_reset(SOCFPGA_RESET(EMAC0), 1);
 102        socfpga_per_reset(SOCFPGA_RESET(EMAC1), 1);
 103
 104        count = fdtdec_find_aliases_for_id(fdt, "ethernet",
 105                                           COMPAT_ALTERA_SOCFPGA_DWMAC,
 106                                           nodes, ARRAY_SIZE(nodes));
 107        for (i = 0; i < count; i++) {
 108                node = nodes[i];
 109                if (node <= 0)
 110                        continue;
 111
 112                ret = fdtdec_parse_phandle_with_args(fdt, node, "resets",
 113                                                     "#reset-cells", 1, 0,
 114                                                     &args);
 115                if (ret || (args.args_count != 1)) {
 116                        debug("GMAC%i: Failed to parse DT 'resets'!\n", i);
 117                        continue;
 118                }
 119
 120                phy_mode = fdt_getprop(fdt, node, "phy-mode", NULL);
 121                ret = dwmac_phymode_to_modereg(phy_mode, &phy_modereg);
 122                if (ret) {
 123                        debug("GMAC%i: Failed to parse DT 'phy-mode'!\n", i);
 124                        continue;
 125                }
 126
 127                dwmac_deassert_reset(args.args[0], phy_modereg);
 128        }
 129
 130        return 0;
 131}
 132#else
 133static int socfpga_eth_reset(void)
 134{
 135        return 0;
 136};
 137#endif
 138
 139static const struct {
 140        const u16       pn;
 141        const char      *name;
 142        const char      *var;
 143} socfpga_fpga_model[] = {
 144        /* Cyclone V E */
 145        { 0x2b15, "Cyclone V, E/A2", "cv_e_a2" },
 146        { 0x2b05, "Cyclone V, E/A4", "cv_e_a4" },
 147        { 0x2b22, "Cyclone V, E/A5", "cv_e_a5" },
 148        { 0x2b13, "Cyclone V, E/A7", "cv_e_a7" },
 149        { 0x2b14, "Cyclone V, E/A9", "cv_e_a9" },
 150        /* Cyclone V GX/GT */
 151        { 0x2b01, "Cyclone V, GX/C3", "cv_gx_c3" },
 152        { 0x2b12, "Cyclone V, GX/C4", "cv_gx_c4" },
 153        { 0x2b02, "Cyclone V, GX/C5 or GT/D5", "cv_gx_c5" },
 154        { 0x2b03, "Cyclone V, GX/C7 or GT/D7", "cv_gx_c7" },
 155        { 0x2b04, "Cyclone V, GX/C9 or GT/D9", "cv_gx_c9" },
 156        /* Cyclone V SE/SX/ST */
 157        { 0x2d11, "Cyclone V, SE/A2 or SX/C2", "cv_se_a2" },
 158        { 0x2d01, "Cyclone V, SE/A4 or SX/C4", "cv_se_a4" },
 159        { 0x2d12, "Cyclone V, SE/A5 or SX/C5 or ST/D5", "cv_se_a5" },
 160        { 0x2d02, "Cyclone V, SE/A6 or SX/C6 or ST/D6", "cv_se_a6" },
 161        /* Arria V */
 162        { 0x2d03, "Arria V, D5", "av_d5" },
 163};
 164
 165static int socfpga_fpga_id(const bool print_id)
 166{
 167        const u32 altera_mi = 0x6e;
 168        const u32 id = scan_mgr_get_fpga_id();
 169
 170        const u32 lsb = id & 0x00000001;
 171        const u32 mi = (id >> 1) & 0x000007ff;
 172        const u32 pn = (id >> 12) & 0x0000ffff;
 173        const u32 version = (id >> 28) & 0x0000000f;
 174        int i;
 175
 176        if ((mi != altera_mi) || (lsb != 1)) {
 177                printf("FPGA:  Not Altera chip ID\n");
 178                return -EINVAL;
 179        }
 180
 181        for (i = 0; i < ARRAY_SIZE(socfpga_fpga_model); i++)
 182                if (pn == socfpga_fpga_model[i].pn)
 183                        break;
 184
 185        if (i == ARRAY_SIZE(socfpga_fpga_model)) {
 186                printf("FPGA:  Unknown Altera chip, ID 0x%08x\n", id);
 187                return -EINVAL;
 188        }
 189
 190        if (print_id)
 191                printf("FPGA:  Altera %s, version 0x%01x\n",
 192                       socfpga_fpga_model[i].name, version);
 193        return i;
 194}
 195
 196/*
 197 * Print CPU information
 198 */
 199#if defined(CONFIG_DISPLAY_CPUINFO)
 200int print_cpuinfo(void)
 201{
 202        const u32 bsel =
 203                SYSMGR_GET_BOOTINFO_BSEL(readl(&sysmgr_regs->bootinfo));
 204
 205        puts("CPU:   Altera SoCFPGA Platform\n");
 206        socfpga_fpga_id(1);
 207
 208        printf("BOOT:  %s\n", bsel_str[bsel].name);
 209        return 0;
 210}
 211#endif
 212
 213#ifdef CONFIG_ARCH_MISC_INIT
 214int arch_misc_init(void)
 215{
 216        const u32 bsel = readl(&sysmgr_regs->bootinfo) & 0x7;
 217        const int fpga_id = socfpga_fpga_id(0);
 218        env_set("bootmode", bsel_str[bsel].mode);
 219        if (fpga_id >= 0)
 220                env_set("fpgatype", socfpga_fpga_model[fpga_id].var);
 221        return socfpga_eth_reset();
 222}
 223#endif
 224
 225/*
 226 * Convert all NIC-301 AMBA slaves from secure to non-secure
 227 */
 228static void socfpga_nic301_slave_ns(void)
 229{
 230        writel(0x1, &nic301_regs->lwhps2fpgaregs);
 231        writel(0x1, &nic301_regs->hps2fpgaregs);
 232        writel(0x1, &nic301_regs->acp);
 233        writel(0x1, &nic301_regs->rom);
 234        writel(0x1, &nic301_regs->ocram);
 235        writel(0x1, &nic301_regs->sdrdata);
 236}
 237
 238static u32 iswgrp_handoff[8];
 239
 240int arch_early_init_r(void)
 241{
 242        int i;
 243
 244        /*
 245         * Write magic value into magic register to unlock support for
 246         * issuing warm reset. The ancient kernel code expects this
 247         * value to be written into the register by the bootloader, so
 248         * to support that old code, we write it here instead of in the
 249         * reset_cpu() function just before resetting the CPU.
 250         */
 251        writel(0xae9efebc, &sysmgr_regs->romcodegrp_warmramgrp_enable);
 252
 253        for (i = 0; i < 8; i++) /* Cache initial SW setting regs */
 254                iswgrp_handoff[i] = readl(&sysmgr_regs->iswgrp_handoff[i]);
 255
 256        socfpga_bridges_reset(1);
 257
 258        socfpga_nic301_slave_ns();
 259
 260        /*
 261         * Private components security:
 262         * U-Boot : configure private timer, global timer and cpu component
 263         * access as non secure for kernel stage (as required by Linux)
 264         */
 265        setbits_le32(&scu_regs->sacr, 0xfff);
 266
 267        /* Configure the L2 controller to make SDRAM start at 0 */
 268#ifdef CONFIG_SOCFPGA_VIRTUAL_TARGET
 269        writel(0x2, &nic301_regs->remap);
 270#else
 271        writel(0x1, &nic301_regs->remap);       /* remap.mpuzero */
 272        writel(0x1, &pl310->pl310_addr_filter_start);
 273#endif
 274
 275        /* Add device descriptor to FPGA device table */
 276        socfpga_fpga_add();
 277
 278#ifdef CONFIG_DESIGNWARE_SPI
 279        /* Get Designware SPI controller out of reset */
 280        socfpga_per_reset(SOCFPGA_RESET(SPIM0), 0);
 281        socfpga_per_reset(SOCFPGA_RESET(SPIM1), 0);
 282#endif
 283
 284#ifdef CONFIG_NAND_DENALI
 285        socfpga_per_reset(SOCFPGA_RESET(NAND), 0);
 286#endif
 287
 288        return 0;
 289}
 290
 291#ifndef CONFIG_SPL_BUILD
 292static struct socfpga_reset_manager *reset_manager_base =
 293        (struct socfpga_reset_manager *)SOCFPGA_RSTMGR_ADDRESS;
 294static struct socfpga_sdr_ctrl *sdr_ctrl =
 295        (struct socfpga_sdr_ctrl *)SDR_CTRLGRP_ADDRESS;
 296
 297static void socfpga_sdram_apply_static_cfg(void)
 298{
 299        const u32 applymask = 0x8;
 300        u32 val = readl(&sdr_ctrl->static_cfg) | applymask;
 301
 302        /*
 303         * SDRAM staticcfg register specific:
 304         * When applying the register setting, the CPU must not access
 305         * SDRAM. Luckily for us, we can abuse i-cache here to help us
 306         * circumvent the SDRAM access issue. The idea is to make sure
 307         * that the code is in one full i-cache line by branching past
 308         * it and back. Once it is in the i-cache, we execute the core
 309         * of the code and apply the register settings.
 310         *
 311         * The code below uses 7 instructions, while the Cortex-A9 has
 312         * 32-byte cachelines, thus the limit is 8 instructions total.
 313         */
 314        asm volatile(
 315                ".align 5                       \n"
 316                "       b       2f              \n"
 317                "1:     str     %0,     [%1]    \n"
 318                "       dsb                     \n"
 319                "       isb                     \n"
 320                "       b       3f              \n"
 321                "2:     b       1b              \n"
 322                "3:     nop                     \n"
 323        : : "r"(val), "r"(&sdr_ctrl->static_cfg) : "memory", "cc");
 324}
 325
 326static int do_bridge(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 327{
 328        if (argc != 2)
 329                return CMD_RET_USAGE;
 330
 331        argv++;
 332
 333        switch (*argv[0]) {
 334        case 'e':       /* Enable */
 335                writel(iswgrp_handoff[2], &sysmgr_regs->fpgaintfgrp_module);
 336                socfpga_sdram_apply_static_cfg();
 337                writel(iswgrp_handoff[3], &sdr_ctrl->fpgaport_rst);
 338                writel(iswgrp_handoff[0], &reset_manager_base->brg_mod_reset);
 339                writel(iswgrp_handoff[1], &nic301_regs->remap);
 340                break;
 341        case 'd':       /* Disable */
 342                writel(0, &sysmgr_regs->fpgaintfgrp_module);
 343                writel(0, &sdr_ctrl->fpgaport_rst);
 344                socfpga_sdram_apply_static_cfg();
 345                writel(0, &reset_manager_base->brg_mod_reset);
 346                writel(1, &nic301_regs->remap);
 347                break;
 348        default:
 349                return CMD_RET_USAGE;
 350        }
 351
 352        return 0;
 353}
 354
 355U_BOOT_CMD(
 356        bridge, 2, 1, do_bridge,
 357        "SoCFPGA HPS FPGA bridge control",
 358        "enable  - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
 359        "bridge disable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
 360        ""
 361);
 362#endif
 363