xref: /rk3399_rockchip-uboot/drivers/fpga/socfpga_arria10.c (revision b491b49882fc71838b46c47a860daf2978c80be4)
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