12baa9972STien Fong Chee /*
22baa9972STien Fong Chee * Copyright (C) 2017 Intel Corporation <www.intel.com>
32baa9972STien Fong Chee *
42baa9972STien Fong Chee * SPDX-License-Identifier: GPL-2.0
52baa9972STien Fong Chee */
62baa9972STien Fong Chee
72baa9972STien Fong Chee #include <asm/io.h>
82baa9972STien Fong Chee #include <asm/arch/fpga_manager.h>
92baa9972STien Fong Chee #include <asm/arch/reset_manager.h>
102baa9972STien Fong Chee #include <asm/arch/system_manager.h>
112baa9972STien Fong Chee #include <asm/arch/sdram.h>
122baa9972STien Fong Chee #include <asm/arch/misc.h>
132baa9972STien Fong Chee #include <altera.h>
142baa9972STien Fong Chee #include <common.h>
152baa9972STien Fong Chee #include <errno.h>
162baa9972STien Fong Chee #include <wait_bit.h>
172baa9972STien Fong Chee #include <watchdog.h>
182baa9972STien Fong Chee
192baa9972STien Fong Chee #define CFGWDTH_32 1
202baa9972STien Fong Chee #define MIN_BITSTREAM_SIZECHECK 230
212baa9972STien Fong Chee #define ENCRYPTION_OFFSET 69
222baa9972STien Fong Chee #define COMPRESSION_OFFSET 229
232baa9972STien Fong Chee #define FPGA_TIMEOUT_MSEC 1000 /* timeout in ms */
242baa9972STien Fong Chee #define FPGA_TIMEOUT_CNT 0x1000000
252baa9972STien Fong Chee
262baa9972STien Fong Chee DECLARE_GLOBAL_DATA_PTR;
272baa9972STien Fong Chee
282baa9972STien Fong Chee static const struct socfpga_fpga_manager *fpga_manager_base =
292baa9972STien Fong Chee (void *)SOCFPGA_FPGAMGRREGS_ADDRESS;
302baa9972STien Fong Chee
312baa9972STien Fong Chee static const struct socfpga_system_manager *system_manager_base =
322baa9972STien Fong Chee (void *)SOCFPGA_SYSMGR_ADDRESS;
332baa9972STien Fong Chee
342baa9972STien Fong Chee static void fpgamgr_set_cd_ratio(unsigned long ratio);
352baa9972STien Fong Chee
fpgamgr_get_msel(void)362baa9972STien Fong Chee static uint32_t fpgamgr_get_msel(void)
372baa9972STien Fong Chee {
382baa9972STien Fong Chee u32 reg;
392baa9972STien Fong Chee
402baa9972STien Fong Chee reg = readl(&fpga_manager_base->imgcfg_stat);
412baa9972STien Fong Chee reg = (reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SET_MSD) >>
422baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_MSEL0_LSB;
432baa9972STien Fong Chee
442baa9972STien Fong Chee return reg;
452baa9972STien Fong Chee }
462baa9972STien Fong Chee
fpgamgr_set_cfgwdth(int width)472baa9972STien Fong Chee static void fpgamgr_set_cfgwdth(int width)
482baa9972STien Fong Chee {
492baa9972STien Fong Chee if (width)
502baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
512baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SET_MSK);
522baa9972STien Fong Chee else
532baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
542baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SET_MSK);
552baa9972STien Fong Chee }
562baa9972STien Fong Chee
is_fpgamgr_user_mode(void)572baa9972STien Fong Chee int is_fpgamgr_user_mode(void)
582baa9972STien Fong Chee {
592baa9972STien Fong Chee return (readl(&fpga_manager_base->imgcfg_stat) &
602baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) != 0;
612baa9972STien Fong Chee }
622baa9972STien Fong Chee
wait_for_user_mode(void)632baa9972STien Fong Chee static int wait_for_user_mode(void)
642baa9972STien Fong Chee {
65*b491b498SJon Lin return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
662baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK,
672baa9972STien Fong Chee 1, FPGA_TIMEOUT_MSEC, false);
682baa9972STien Fong Chee }
692baa9972STien Fong Chee
is_fpgamgr_early_user_mode(void)702baa9972STien Fong Chee static int is_fpgamgr_early_user_mode(void)
712baa9972STien Fong Chee {
722baa9972STien Fong Chee return (readl(&fpga_manager_base->imgcfg_stat) &
732baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK) != 0;
742baa9972STien Fong Chee }
752baa9972STien Fong Chee
fpgamgr_wait_early_user_mode(void)762baa9972STien Fong Chee int fpgamgr_wait_early_user_mode(void)
772baa9972STien Fong Chee {
782baa9972STien Fong Chee u32 sync_data = 0xffffffff;
792baa9972STien Fong Chee u32 i = 0;
802baa9972STien Fong Chee unsigned start = get_timer(0);
812baa9972STien Fong Chee unsigned long cd_ratio;
822baa9972STien Fong Chee
832baa9972STien Fong Chee /* Getting existing CDRATIO */
842baa9972STien Fong Chee cd_ratio = (readl(&fpga_manager_base->imgcfg_ctrl_02) &
852baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK) >>
862baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_LSB;
872baa9972STien Fong Chee
882baa9972STien Fong Chee /* Using CDRATIO_X1 for better compatibility */
892baa9972STien Fong Chee fpgamgr_set_cd_ratio(CDRATIO_x1);
902baa9972STien Fong Chee
912baa9972STien Fong Chee while (!is_fpgamgr_early_user_mode()) {
922baa9972STien Fong Chee if (get_timer(start) > FPGA_TIMEOUT_MSEC)
932baa9972STien Fong Chee return -ETIMEDOUT;
942baa9972STien Fong Chee fpgamgr_program_write((const long unsigned int *)&sync_data,
952baa9972STien Fong Chee sizeof(sync_data));
962baa9972STien Fong Chee udelay(FPGA_TIMEOUT_MSEC);
972baa9972STien Fong Chee i++;
982baa9972STien Fong Chee }
992baa9972STien Fong Chee
1002baa9972STien Fong Chee debug("Additional %i sync word needed\n", i);
1012baa9972STien Fong Chee
1022baa9972STien Fong Chee /* restoring original CDRATIO */
1032baa9972STien Fong Chee fpgamgr_set_cd_ratio(cd_ratio);
1042baa9972STien Fong Chee
1052baa9972STien Fong Chee return 0;
1062baa9972STien Fong Chee }
1072baa9972STien Fong Chee
1082baa9972STien Fong Chee /* Read f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted */
wait_for_nconfig_pin_and_nstatus_pin(void)1092baa9972STien Fong Chee static int wait_for_nconfig_pin_and_nstatus_pin(void)
1102baa9972STien Fong Chee {
1112baa9972STien Fong Chee unsigned long mask = ALT_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN_SET_MSK |
1122baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK;
1132baa9972STien Fong Chee
1142baa9972STien Fong Chee /* Poll until f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted,
1152baa9972STien Fong Chee * timeout at 1000ms
1162baa9972STien Fong Chee */
117*b491b498SJon Lin return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
1182baa9972STien Fong Chee mask,
1192baa9972STien Fong Chee false, FPGA_TIMEOUT_MSEC, false);
1202baa9972STien Fong Chee }
1212baa9972STien Fong Chee
wait_for_f2s_nstatus_pin(unsigned long value)1222baa9972STien Fong Chee static int wait_for_f2s_nstatus_pin(unsigned long value)
1232baa9972STien Fong Chee {
1242baa9972STien Fong Chee /* Poll until f2s to specific value, timeout at 1000ms */
125*b491b498SJon Lin return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
1262baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
1272baa9972STien Fong Chee value, FPGA_TIMEOUT_MSEC, false);
1282baa9972STien Fong Chee }
1292baa9972STien Fong Chee
1302baa9972STien Fong Chee /* set CD ratio */
fpgamgr_set_cd_ratio(unsigned long ratio)1312baa9972STien Fong Chee static void fpgamgr_set_cd_ratio(unsigned long ratio)
1322baa9972STien Fong Chee {
1332baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
1342baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK);
1352baa9972STien Fong Chee
1362baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
1372baa9972STien Fong Chee (ratio << ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_LSB) &
1382baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK);
1392baa9972STien Fong Chee }
1402baa9972STien Fong Chee
1412baa9972STien Fong Chee /* get the MSEL value, verify we are set for FPP configuration mode */
fpgamgr_verify_msel(void)1422baa9972STien Fong Chee static int fpgamgr_verify_msel(void)
1432baa9972STien Fong Chee {
1442baa9972STien Fong Chee u32 msel = fpgamgr_get_msel();
1452baa9972STien Fong Chee
1462baa9972STien Fong Chee if (msel & ~BIT(0)) {
1472baa9972STien Fong Chee printf("Fail: read msel=%d\n", msel);
1482baa9972STien Fong Chee return -EPERM;
1492baa9972STien Fong Chee }
1502baa9972STien Fong Chee
1512baa9972STien Fong Chee return 0;
1522baa9972STien Fong Chee }
1532baa9972STien Fong Chee
1542baa9972STien Fong Chee /*
1552baa9972STien Fong Chee * Write cdratio and cdwidth based on whether the bitstream is compressed
1562baa9972STien Fong Chee * and/or encoded
1572baa9972STien Fong Chee */
fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width,u32 * rbf_data,size_t rbf_size)1582baa9972STien Fong Chee static int fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width, u32 *rbf_data,
1592baa9972STien Fong Chee size_t rbf_size)
1602baa9972STien Fong Chee {
1612baa9972STien Fong Chee unsigned int cd_ratio;
1622baa9972STien Fong Chee bool encrypt, compress;
1632baa9972STien Fong Chee
1642baa9972STien Fong Chee /*
1652baa9972STien Fong Chee * According to the bitstream specification,
1662baa9972STien Fong Chee * both encryption and compression status are
1672baa9972STien Fong Chee * in location before offset 230 of the buffer.
1682baa9972STien Fong Chee */
1692baa9972STien Fong Chee if (rbf_size < MIN_BITSTREAM_SIZECHECK)
1702baa9972STien Fong Chee return -EINVAL;
1712baa9972STien Fong Chee
1722baa9972STien Fong Chee encrypt = (rbf_data[ENCRYPTION_OFFSET] >> 2) & 3;
1732baa9972STien Fong Chee encrypt = encrypt != 0;
1742baa9972STien Fong Chee
1752baa9972STien Fong Chee compress = (rbf_data[COMPRESSION_OFFSET] >> 1) & 1;
1762baa9972STien Fong Chee compress = !compress;
1772baa9972STien Fong Chee
1782baa9972STien Fong Chee debug("header word %d = %08x\n", 69, rbf_data[69]);
1792baa9972STien Fong Chee debug("header word %d = %08x\n", 229, rbf_data[229]);
1802baa9972STien Fong Chee debug("read from rbf header: encrypt=%d compress=%d\n", encrypt, compress);
1812baa9972STien Fong Chee
1822baa9972STien Fong Chee /*
1832baa9972STien Fong Chee * from the register map description of cdratio in imgcfg_ctrl_02:
1842baa9972STien Fong Chee * Normal Configuration : 32bit Passive Parallel
1852baa9972STien Fong Chee * Partial Reconfiguration : 16bit Passive Parallel
1862baa9972STien Fong Chee */
1872baa9972STien Fong Chee
1882baa9972STien Fong Chee /*
1892baa9972STien Fong Chee * cd ratio is dependent on cfg width and whether the bitstream
1902baa9972STien Fong Chee * is encrypted and/or compressed.
1912baa9972STien Fong Chee *
1922baa9972STien Fong Chee * | width | encr. | compr. | cd ratio |
1932baa9972STien Fong Chee * | 16 | 0 | 0 | 1 |
1942baa9972STien Fong Chee * | 16 | 0 | 1 | 4 |
1952baa9972STien Fong Chee * | 16 | 1 | 0 | 2 |
1962baa9972STien Fong Chee * | 16 | 1 | 1 | 4 |
1972baa9972STien Fong Chee * | 32 | 0 | 0 | 1 |
1982baa9972STien Fong Chee * | 32 | 0 | 1 | 8 |
1992baa9972STien Fong Chee * | 32 | 1 | 0 | 4 |
2002baa9972STien Fong Chee * | 32 | 1 | 1 | 8 |
2012baa9972STien Fong Chee */
2022baa9972STien Fong Chee if (!compress && !encrypt) {
2032baa9972STien Fong Chee cd_ratio = CDRATIO_x1;
2042baa9972STien Fong Chee } else {
2052baa9972STien Fong Chee if (compress)
2062baa9972STien Fong Chee cd_ratio = CDRATIO_x4;
2072baa9972STien Fong Chee else
2082baa9972STien Fong Chee cd_ratio = CDRATIO_x2;
2092baa9972STien Fong Chee
2102baa9972STien Fong Chee /* if 32 bit, double the cd ratio (so register
2112baa9972STien Fong Chee field setting is incremented) */
2122baa9972STien Fong Chee if (cfg_width == CFGWDTH_32)
2132baa9972STien Fong Chee cd_ratio += 1;
2142baa9972STien Fong Chee }
2152baa9972STien Fong Chee
2162baa9972STien Fong Chee fpgamgr_set_cfgwdth(cfg_width);
2172baa9972STien Fong Chee fpgamgr_set_cd_ratio(cd_ratio);
2182baa9972STien Fong Chee
2192baa9972STien Fong Chee return 0;
2202baa9972STien Fong Chee }
2212baa9972STien Fong Chee
fpgamgr_reset(void)2222baa9972STien Fong Chee static int fpgamgr_reset(void)
2232baa9972STien Fong Chee {
2242baa9972STien Fong Chee unsigned long reg;
2252baa9972STien Fong Chee
2262baa9972STien Fong Chee /* S2F_NCONFIG = 0 */
2272baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
2282baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
2292baa9972STien Fong Chee
2302baa9972STien Fong Chee /* Wait for f2s_nstatus == 0 */
2312baa9972STien Fong Chee if (wait_for_f2s_nstatus_pin(0))
2322baa9972STien Fong Chee return -ETIME;
2332baa9972STien Fong Chee
2342baa9972STien Fong Chee /* S2F_NCONFIG = 1 */
2352baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
2362baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
2372baa9972STien Fong Chee
2382baa9972STien Fong Chee /* Wait for f2s_nstatus == 1 */
2392baa9972STien Fong Chee if (wait_for_f2s_nstatus_pin(1))
2402baa9972STien Fong Chee return -ETIME;
2412baa9972STien Fong Chee
2422baa9972STien Fong Chee /* read and confirm f2s_condone_pin = 0 and f2s_condone_oe = 1 */
2432baa9972STien Fong Chee reg = readl(&fpga_manager_base->imgcfg_stat);
2442baa9972STien Fong Chee if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) != 0)
2452baa9972STien Fong Chee return -EPERM;
2462baa9972STien Fong Chee
2472baa9972STien Fong Chee if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_OE_SET_MSK) == 0)
2482baa9972STien Fong Chee return -EPERM;
2492baa9972STien Fong Chee
2502baa9972STien Fong Chee return 0;
2512baa9972STien Fong Chee }
2522baa9972STien Fong Chee
2532baa9972STien Fong Chee /* Start the FPGA programming by initialize the FPGA Manager */
fpgamgr_program_init(u32 * rbf_data,size_t rbf_size)2542baa9972STien Fong Chee int fpgamgr_program_init(u32 * rbf_data, size_t rbf_size)
2552baa9972STien Fong Chee {
2562baa9972STien Fong Chee int ret;
2572baa9972STien Fong Chee
2582baa9972STien Fong Chee /* Step 1 */
2592baa9972STien Fong Chee if (fpgamgr_verify_msel())
2602baa9972STien Fong Chee return -EPERM;
2612baa9972STien Fong Chee
2622baa9972STien Fong Chee /* Step 2 */
2632baa9972STien Fong Chee if (fpgamgr_set_cdratio_cdwidth(CFGWDTH_32, rbf_data, rbf_size))
2642baa9972STien Fong Chee return -EPERM;
2652baa9972STien Fong Chee
2662baa9972STien Fong Chee /*
2672baa9972STien Fong Chee * Step 3:
2682baa9972STien Fong Chee * Make sure no other external devices are trying to interfere with
2692baa9972STien Fong Chee * programming:
2702baa9972STien Fong Chee */
2712baa9972STien Fong Chee if (wait_for_nconfig_pin_and_nstatus_pin())
2722baa9972STien Fong Chee return -ETIME;
2732baa9972STien Fong Chee
2742baa9972STien Fong Chee /*
2752baa9972STien Fong Chee * Step 4:
2762baa9972STien Fong Chee * Deassert the signal drives from HPS
2772baa9972STien Fong Chee *
2782baa9972STien Fong Chee * S2F_NCE = 1
2792baa9972STien Fong Chee * S2F_PR_REQUEST = 0
2802baa9972STien Fong Chee * EN_CFG_CTRL = 0
2812baa9972STien Fong Chee * EN_CFG_DATA = 0
2822baa9972STien Fong Chee * S2F_NCONFIG = 1
2832baa9972STien Fong Chee * S2F_NSTATUS_OE = 0
2842baa9972STien Fong Chee * S2F_CONDONE_OE = 0
2852baa9972STien Fong Chee */
2862baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
2872baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
2882baa9972STien Fong Chee
2892baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
2902baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST_SET_MSK);
2912baa9972STien Fong Chee
2922baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
2932baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
2942baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
2952baa9972STien Fong Chee
2962baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
2972baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
2982baa9972STien Fong Chee
2992baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
3002baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE_SET_MSK |
3012baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE_SET_MSK);
3022baa9972STien Fong Chee
3032baa9972STien Fong Chee /*
3042baa9972STien Fong Chee * Step 5:
3052baa9972STien Fong Chee * Enable overrides
3062baa9972STien Fong Chee * S2F_NENABLE_CONFIG = 0
3072baa9972STien Fong Chee * S2F_NENABLE_NCONFIG = 0
3082baa9972STien Fong Chee */
3092baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
3102baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG_SET_MSK);
3112baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
3122baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG_SET_MSK);
3132baa9972STien Fong Chee
3142baa9972STien Fong Chee /*
3152baa9972STien Fong Chee * Disable driving signals that HPS doesn't need to drive.
3162baa9972STien Fong Chee * S2F_NENABLE_NSTATUS = 1
3172baa9972STien Fong Chee * S2F_NENABLE_CONDONE = 1
3182baa9972STien Fong Chee */
3192baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
3202baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS_SET_MSK |
3212baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE_SET_MSK);
3222baa9972STien Fong Chee
3232baa9972STien Fong Chee /*
3242baa9972STien Fong Chee * Step 6:
3252baa9972STien Fong Chee * Drive chip select S2F_NCE = 0
3262baa9972STien Fong Chee */
3272baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
3282baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
3292baa9972STien Fong Chee
3302baa9972STien Fong Chee /* Step 7 */
3312baa9972STien Fong Chee if (wait_for_nconfig_pin_and_nstatus_pin())
3322baa9972STien Fong Chee return -ETIME;
3332baa9972STien Fong Chee
3342baa9972STien Fong Chee /* Step 8 */
3352baa9972STien Fong Chee ret = fpgamgr_reset();
3362baa9972STien Fong Chee
3372baa9972STien Fong Chee if (ret)
3382baa9972STien Fong Chee return ret;
3392baa9972STien Fong Chee
3402baa9972STien Fong Chee /*
3412baa9972STien Fong Chee * Step 9:
3422baa9972STien Fong Chee * EN_CFG_CTRL and EN_CFG_DATA = 1
3432baa9972STien Fong Chee */
3442baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
3452baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
3462baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
3472baa9972STien Fong Chee
3482baa9972STien Fong Chee return 0;
3492baa9972STien Fong Chee }
3502baa9972STien Fong Chee
3512baa9972STien Fong Chee /* Ensure the FPGA entering config done */
fpgamgr_program_poll_cd(void)3522baa9972STien Fong Chee static int fpgamgr_program_poll_cd(void)
3532baa9972STien Fong Chee {
3542baa9972STien Fong Chee unsigned long reg, i;
3552baa9972STien Fong Chee
3562baa9972STien Fong Chee for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
3572baa9972STien Fong Chee reg = readl(&fpga_manager_base->imgcfg_stat);
3582baa9972STien Fong Chee if (reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK)
3592baa9972STien Fong Chee return 0;
3602baa9972STien Fong Chee
3612baa9972STien Fong Chee if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK) == 0) {
3622baa9972STien Fong Chee printf("nstatus == 0 while waiting for condone\n");
3632baa9972STien Fong Chee return -EPERM;
3642baa9972STien Fong Chee }
3652baa9972STien Fong Chee }
3662baa9972STien Fong Chee
3672baa9972STien Fong Chee if (i == FPGA_TIMEOUT_CNT)
3682baa9972STien Fong Chee return -ETIME;
3692baa9972STien Fong Chee
3702baa9972STien Fong Chee return 0;
3712baa9972STien Fong Chee }
3722baa9972STien Fong Chee
3732baa9972STien Fong Chee /* Ensure the FPGA entering user mode */
fpgamgr_program_poll_usermode(void)3742baa9972STien Fong Chee static int fpgamgr_program_poll_usermode(void)
3752baa9972STien Fong Chee {
3762baa9972STien Fong Chee unsigned long reg;
3772baa9972STien Fong Chee int ret = 0;
3782baa9972STien Fong Chee
3792baa9972STien Fong Chee if (fpgamgr_dclkcnt_set(0xf))
3802baa9972STien Fong Chee return -ETIME;
3812baa9972STien Fong Chee
3822baa9972STien Fong Chee ret = wait_for_user_mode();
3832baa9972STien Fong Chee if (ret < 0) {
3842baa9972STien Fong Chee printf("%s: Failed to enter user mode with ", __func__);
3852baa9972STien Fong Chee printf("error code %d\n", ret);
3862baa9972STien Fong Chee return ret;
3872baa9972STien Fong Chee }
3882baa9972STien Fong Chee
3892baa9972STien Fong Chee /*
3902baa9972STien Fong Chee * Step 14:
3912baa9972STien Fong Chee * Stop DATA path and Dclk
3922baa9972STien Fong Chee * EN_CFG_CTRL and EN_CFG_DATA = 0
3932baa9972STien Fong Chee */
3942baa9972STien Fong Chee clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
3952baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
3962baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
3972baa9972STien Fong Chee
3982baa9972STien Fong Chee /*
3992baa9972STien Fong Chee * Step 15:
4002baa9972STien Fong Chee * Disable overrides
4012baa9972STien Fong Chee * S2F_NENABLE_CONFIG = 1
4022baa9972STien Fong Chee * S2F_NENABLE_NCONFIG = 1
4032baa9972STien Fong Chee */
4042baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
4052baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG_SET_MSK);
4062baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
4072baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG_SET_MSK);
4082baa9972STien Fong Chee
4092baa9972STien Fong Chee /* Disable chip select S2F_NCE = 1 */
4102baa9972STien Fong Chee setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
4112baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
4122baa9972STien Fong Chee
4132baa9972STien Fong Chee /*
4142baa9972STien Fong Chee * Step 16:
4152baa9972STien Fong Chee * Final check
4162baa9972STien Fong Chee */
4172baa9972STien Fong Chee reg = readl(&fpga_manager_base->imgcfg_stat);
4182baa9972STien Fong Chee if (((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) !=
4192baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) ||
4202baa9972STien Fong Chee ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) !=
4212baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) ||
4222baa9972STien Fong Chee ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK) !=
4232baa9972STien Fong Chee ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK))
4242baa9972STien Fong Chee return -EPERM;
4252baa9972STien Fong Chee
4262baa9972STien Fong Chee return 0;
4272baa9972STien Fong Chee }
4282baa9972STien Fong Chee
fpgamgr_program_finish(void)4292baa9972STien Fong Chee int fpgamgr_program_finish(void)
4302baa9972STien Fong Chee {
4312baa9972STien Fong Chee /* Ensure the FPGA entering config done */
4322baa9972STien Fong Chee int status = fpgamgr_program_poll_cd();
4332baa9972STien Fong Chee
4342baa9972STien Fong Chee if (status) {
4352baa9972STien Fong Chee printf("FPGA: Poll CD failed with error code %d\n", status);
4362baa9972STien Fong Chee return -EPERM;
4372baa9972STien Fong Chee }
4382baa9972STien Fong Chee WATCHDOG_RESET();
4392baa9972STien Fong Chee
4402baa9972STien Fong Chee /* Ensure the FPGA entering user mode */
4412baa9972STien Fong Chee status = fpgamgr_program_poll_usermode();
4422baa9972STien Fong Chee if (status) {
4432baa9972STien Fong Chee printf("FPGA: Poll usermode failed with error code %d\n",
4442baa9972STien Fong Chee status);
4452baa9972STien Fong Chee return -EPERM;
4462baa9972STien Fong Chee }
4472baa9972STien Fong Chee
4482baa9972STien Fong Chee printf("Full Configuration Succeeded.\n");
4492baa9972STien Fong Chee
4502baa9972STien Fong Chee return 0;
4512baa9972STien Fong Chee }
4522baa9972STien Fong Chee
4532baa9972STien Fong Chee /*
4542baa9972STien Fong Chee * FPGA Manager to program the FPGA. This is the interface used by FPGA driver.
4552baa9972STien Fong Chee * Return 0 for sucess, non-zero for error.
4562baa9972STien Fong Chee */
socfpga_load(Altera_desc * desc,const void * rbf_data,size_t rbf_size)4572baa9972STien Fong Chee int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
4582baa9972STien Fong Chee {
4592baa9972STien Fong Chee unsigned long status;
4602baa9972STien Fong Chee
4612baa9972STien Fong Chee /* disable all signals from hps peripheral controller to fpga */
4622baa9972STien Fong Chee writel(0, &system_manager_base->fpgaintf_en_global);
4632baa9972STien Fong Chee
4642baa9972STien Fong Chee /* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
4652baa9972STien Fong Chee socfpga_bridges_reset();
4662baa9972STien Fong Chee
4672baa9972STien Fong Chee /* Initialize the FPGA Manager */
4682baa9972STien Fong Chee status = fpgamgr_program_init((u32 *)rbf_data, rbf_size);
4692baa9972STien Fong Chee if (status)
4702baa9972STien Fong Chee return status;
4712baa9972STien Fong Chee
4722baa9972STien Fong Chee /* Write the RBF data to FPGA Manager */
4732baa9972STien Fong Chee fpgamgr_program_write(rbf_data, rbf_size);
4742baa9972STien Fong Chee
4752baa9972STien Fong Chee return fpgamgr_program_finish();
4762baa9972STien Fong Chee }
477