uboot/drivers/fpga/socfpga_gen5.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause
   2/*
   3 * Copyright (C) 2012 Altera Corporation <www.altera.com>
   4 * All rights reserved.
   5 */
   6
   7#include <common.h>
   8#include <asm/io.h>
   9#include <linux/errno.h>
  10#include <asm/arch/fpga_manager.h>
  11#include <asm/arch/reset_manager.h>
  12#include <asm/arch/system_manager.h>
  13
  14#define FPGA_TIMEOUT_CNT        0x1000000
  15
  16static struct socfpga_fpga_manager *fpgamgr_regs =
  17        (struct socfpga_fpga_manager *)SOCFPGA_FPGAMGRREGS_ADDRESS;
  18
  19/* Set CD ratio */
  20static void fpgamgr_set_cd_ratio(unsigned long ratio)
  21{
  22        clrsetbits_le32(&fpgamgr_regs->ctrl,
  23                        0x3 << FPGAMGRREGS_CTRL_CDRATIO_LSB,
  24                        (ratio & 0x3) << FPGAMGRREGS_CTRL_CDRATIO_LSB);
  25}
  26
  27/* Start the FPGA programming by initialize the FPGA Manager */
  28static int fpgamgr_program_init(void)
  29{
  30        unsigned long msel, i;
  31
  32        /* Get the MSEL value */
  33        msel = readl(&fpgamgr_regs->stat);
  34        msel &= FPGAMGRREGS_STAT_MSEL_MASK;
  35        msel >>= FPGAMGRREGS_STAT_MSEL_LSB;
  36
  37        /*
  38         * Set the cfg width
  39         * If MSEL[3] = 1, cfg width = 32 bit
  40         */
  41        if (msel & 0x8) {
  42                setbits_le32(&fpgamgr_regs->ctrl,
  43                             FPGAMGRREGS_CTRL_CFGWDTH_MASK);
  44
  45                /* To determine the CD ratio */
  46                /* MSEL[1:0] = 0, CD Ratio = 1 */
  47                if ((msel & 0x3) == 0x0)
  48                        fpgamgr_set_cd_ratio(CDRATIO_x1);
  49                /* MSEL[1:0] = 1, CD Ratio = 4 */
  50                else if ((msel & 0x3) == 0x1)
  51                        fpgamgr_set_cd_ratio(CDRATIO_x4);
  52                /* MSEL[1:0] = 2, CD Ratio = 8 */
  53                else if ((msel & 0x3) == 0x2)
  54                        fpgamgr_set_cd_ratio(CDRATIO_x8);
  55
  56        } else {        /* MSEL[3] = 0 */
  57                clrbits_le32(&fpgamgr_regs->ctrl,
  58                             FPGAMGRREGS_CTRL_CFGWDTH_MASK);
  59
  60                /* To determine the CD ratio */
  61                /* MSEL[1:0] = 0, CD Ratio = 1 */
  62                if ((msel & 0x3) == 0x0)
  63                        fpgamgr_set_cd_ratio(CDRATIO_x1);
  64                /* MSEL[1:0] = 1, CD Ratio = 2 */
  65                else if ((msel & 0x3) == 0x1)
  66                        fpgamgr_set_cd_ratio(CDRATIO_x2);
  67                /* MSEL[1:0] = 2, CD Ratio = 4 */
  68                else if ((msel & 0x3) == 0x2)
  69                        fpgamgr_set_cd_ratio(CDRATIO_x4);
  70        }
  71
  72        /* To enable FPGA Manager configuration */
  73        clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCE_MASK);
  74
  75        /* To enable FPGA Manager drive over configuration line */
  76        setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
  77
  78        /* Put FPGA into reset phase */
  79        setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
  80
  81        /* (1) wait until FPGA enter reset phase */
  82        for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
  83                if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_RESETPHASE)
  84                        break;
  85        }
  86
  87        /* If not in reset state, return error */
  88        if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_RESETPHASE) {
  89                puts("FPGA: Could not reset\n");
  90                return -1;
  91        }
  92
  93        /* Release FPGA from reset phase */
  94        clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
  95
  96        /* (2) wait until FPGA enter configuration phase */
  97        for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
  98                if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_CFGPHASE)
  99                        break;
 100        }
 101
 102        /* If not in configuration state, return error */
 103        if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_CFGPHASE) {
 104                puts("FPGA: Could not configure\n");
 105                return -2;
 106        }
 107
 108        /* Clear all interrupts in CB Monitor */
 109        writel(0xFFF, &fpgamgr_regs->gpio_porta_eoi);
 110
 111        /* Enable AXI configuration */
 112        setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
 113
 114        return 0;
 115}
 116
 117/* Ensure the FPGA entering config done */
 118static int fpgamgr_program_poll_cd(void)
 119{
 120        const uint32_t mask = FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK |
 121                              FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK;
 122        unsigned long reg, i;
 123
 124        /* (3) wait until full config done */
 125        for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
 126                reg = readl(&fpgamgr_regs->gpio_ext_porta);
 127
 128                /* Config error */
 129                if (!(reg & mask)) {
 130                        printf("FPGA: Configuration error.\n");
 131                        return -3;
 132                }
 133
 134                /* Config done without error */
 135                if (reg & mask)
 136                        break;
 137        }
 138
 139        /* Timeout happened, return error */
 140        if (i == FPGA_TIMEOUT_CNT) {
 141                printf("FPGA: Timeout waiting for program.\n");
 142                return -4;
 143        }
 144
 145        /* Disable AXI configuration */
 146        clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
 147
 148        return 0;
 149}
 150
 151/* Ensure the FPGA entering init phase */
 152static int fpgamgr_program_poll_initphase(void)
 153{
 154        unsigned long i;
 155
 156        /* Additional clocks for the CB to enter initialization phase */
 157        if (fpgamgr_dclkcnt_set(0x4))
 158                return -5;
 159
 160        /* (4) wait until FPGA enter init phase or user mode */
 161        for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
 162                if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_INITPHASE)
 163                        break;
 164                if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
 165                        break;
 166        }
 167
 168        /* If not in configuration state, return error */
 169        if (i == FPGA_TIMEOUT_CNT)
 170                return -6;
 171
 172        return 0;
 173}
 174
 175/* Ensure the FPGA entering user mode */
 176static int fpgamgr_program_poll_usermode(void)
 177{
 178        unsigned long i;
 179
 180        /* Additional clocks for the CB to exit initialization phase */
 181        if (fpgamgr_dclkcnt_set(0x5000))
 182                return -7;
 183
 184        /* (5) wait until FPGA enter user mode */
 185        for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
 186                if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
 187                        break;
 188        }
 189        /* If not in configuration state, return error */
 190        if (i == FPGA_TIMEOUT_CNT)
 191                return -8;
 192
 193        /* To release FPGA Manager drive over configuration line */
 194        clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
 195
 196        return 0;
 197}
 198
 199/*
 200 * FPGA Manager to program the FPGA. This is the interface used by FPGA driver.
 201 * Return 0 for sucess, non-zero for error.
 202 */
 203int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
 204{
 205        int status;
 206
 207        if ((uint32_t)rbf_data & 0x3) {
 208                puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
 209                return -EINVAL;
 210        }
 211
 212        /* Prior programming the FPGA, all bridges need to be shut off */
 213
 214        /* Disable all signals from hps peripheral controller to fpga */
 215        writel(0, socfpga_get_sysmgr_addr() + SYSMGR_GEN5_FPGAINFGRP_MODULE);
 216
 217        /* Disable all signals from FPGA to HPS SDRAM */
 218#define SDR_CTRLGRP_FPGAPORTRST_ADDRESS 0x5080
 219        writel(0, SOCFPGA_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS);
 220
 221        /* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
 222        socfpga_bridges_reset(1);
 223
 224        /* Unmap the bridges from NIC-301 */
 225        writel(0x1, SOCFPGA_L3REGS_ADDRESS);
 226
 227        /* Initialize the FPGA Manager */
 228        status = fpgamgr_program_init();
 229        if (status)
 230                return status;
 231
 232        /* Write the RBF data to FPGA Manager */
 233        fpgamgr_program_write(rbf_data, rbf_size);
 234
 235        /* Ensure the FPGA entering config done */
 236        status = fpgamgr_program_poll_cd();
 237        if (status)
 238                return status;
 239
 240        /* Ensure the FPGA entering init phase */
 241        status = fpgamgr_program_poll_initphase();
 242        if (status)
 243                return status;
 244
 245        /* Ensure the FPGA entering user mode */
 246        return fpgamgr_program_poll_usermode();
 247}
 248