xref: /OK3568_Linux_fs/u-boot/drivers/fpga/socfpga_arria10.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2017 Intel Corporation <www.intel.com>
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:    GPL-2.0
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <asm/io.h>
8*4882a593Smuzhiyun #include <asm/arch/fpga_manager.h>
9*4882a593Smuzhiyun #include <asm/arch/reset_manager.h>
10*4882a593Smuzhiyun #include <asm/arch/system_manager.h>
11*4882a593Smuzhiyun #include <asm/arch/sdram.h>
12*4882a593Smuzhiyun #include <asm/arch/misc.h>
13*4882a593Smuzhiyun #include <altera.h>
14*4882a593Smuzhiyun #include <common.h>
15*4882a593Smuzhiyun #include <errno.h>
16*4882a593Smuzhiyun #include <wait_bit.h>
17*4882a593Smuzhiyun #include <watchdog.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define CFGWDTH_32	1
20*4882a593Smuzhiyun #define MIN_BITSTREAM_SIZECHECK	230
21*4882a593Smuzhiyun #define ENCRYPTION_OFFSET	69
22*4882a593Smuzhiyun #define COMPRESSION_OFFSET	229
23*4882a593Smuzhiyun #define FPGA_TIMEOUT_MSEC	1000  /* timeout in ms */
24*4882a593Smuzhiyun #define FPGA_TIMEOUT_CNT	0x1000000
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static const struct socfpga_fpga_manager *fpga_manager_base =
29*4882a593Smuzhiyun 		(void *)SOCFPGA_FPGAMGRREGS_ADDRESS;
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun static const struct socfpga_system_manager *system_manager_base =
32*4882a593Smuzhiyun 		(void *)SOCFPGA_SYSMGR_ADDRESS;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun static void fpgamgr_set_cd_ratio(unsigned long ratio);
35*4882a593Smuzhiyun 
fpgamgr_get_msel(void)36*4882a593Smuzhiyun static uint32_t fpgamgr_get_msel(void)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	u32 reg;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	reg = readl(&fpga_manager_base->imgcfg_stat);
41*4882a593Smuzhiyun 	reg = (reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SET_MSD) >>
42*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_STAT_F2S_MSEL0_LSB;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	return reg;
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun 
fpgamgr_set_cfgwdth(int width)47*4882a593Smuzhiyun static void fpgamgr_set_cfgwdth(int width)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	if (width)
50*4882a593Smuzhiyun 		setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
51*4882a593Smuzhiyun 			ALT_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SET_MSK);
52*4882a593Smuzhiyun 	else
53*4882a593Smuzhiyun 		clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
54*4882a593Smuzhiyun 			ALT_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SET_MSK);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
is_fpgamgr_user_mode(void)57*4882a593Smuzhiyun int is_fpgamgr_user_mode(void)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	return (readl(&fpga_manager_base->imgcfg_stat) &
60*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) != 0;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
wait_for_user_mode(void)63*4882a593Smuzhiyun static int wait_for_user_mode(void)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
66*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK,
67*4882a593Smuzhiyun 		1, FPGA_TIMEOUT_MSEC, false);
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
is_fpgamgr_early_user_mode(void)70*4882a593Smuzhiyun static int is_fpgamgr_early_user_mode(void)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	return (readl(&fpga_manager_base->imgcfg_stat) &
73*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK) != 0;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
fpgamgr_wait_early_user_mode(void)76*4882a593Smuzhiyun int fpgamgr_wait_early_user_mode(void)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	u32 sync_data = 0xffffffff;
79*4882a593Smuzhiyun 	u32 i = 0;
80*4882a593Smuzhiyun 	unsigned start = get_timer(0);
81*4882a593Smuzhiyun 	unsigned long cd_ratio;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	/* Getting existing CDRATIO */
84*4882a593Smuzhiyun 	cd_ratio = (readl(&fpga_manager_base->imgcfg_ctrl_02) &
85*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK) >>
86*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_LSB;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* Using CDRATIO_X1 for better compatibility */
89*4882a593Smuzhiyun 	fpgamgr_set_cd_ratio(CDRATIO_x1);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	while (!is_fpgamgr_early_user_mode()) {
92*4882a593Smuzhiyun 		if (get_timer(start) > FPGA_TIMEOUT_MSEC)
93*4882a593Smuzhiyun 			return -ETIMEDOUT;
94*4882a593Smuzhiyun 		fpgamgr_program_write((const long unsigned int *)&sync_data,
95*4882a593Smuzhiyun 				sizeof(sync_data));
96*4882a593Smuzhiyun 		udelay(FPGA_TIMEOUT_MSEC);
97*4882a593Smuzhiyun 		i++;
98*4882a593Smuzhiyun 	}
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	debug("Additional %i sync word needed\n", i);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	/* restoring original CDRATIO */
103*4882a593Smuzhiyun 	fpgamgr_set_cd_ratio(cd_ratio);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	return 0;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun /* Read f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted */
wait_for_nconfig_pin_and_nstatus_pin(void)109*4882a593Smuzhiyun static int wait_for_nconfig_pin_and_nstatus_pin(void)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	unsigned long mask = ALT_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN_SET_MSK |
112*4882a593Smuzhiyun 				ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/* Poll until f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted,
115*4882a593Smuzhiyun 	 * timeout at 1000ms
116*4882a593Smuzhiyun 	 */
117*4882a593Smuzhiyun 	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
118*4882a593Smuzhiyun 		mask,
119*4882a593Smuzhiyun 		false, FPGA_TIMEOUT_MSEC, false);
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
wait_for_f2s_nstatus_pin(unsigned long value)122*4882a593Smuzhiyun static int wait_for_f2s_nstatus_pin(unsigned long value)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	/* Poll until f2s to specific value, timeout at 1000ms */
125*4882a593Smuzhiyun 	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
126*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
127*4882a593Smuzhiyun 		value, FPGA_TIMEOUT_MSEC, false);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun /* set CD ratio */
fpgamgr_set_cd_ratio(unsigned long ratio)131*4882a593Smuzhiyun static void fpgamgr_set_cd_ratio(unsigned long ratio)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
134*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
137*4882a593Smuzhiyun 		(ratio << ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_LSB) &
138*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun /* get the MSEL value, verify we are set for FPP configuration mode */
fpgamgr_verify_msel(void)142*4882a593Smuzhiyun static int fpgamgr_verify_msel(void)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	u32 msel = fpgamgr_get_msel();
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	if (msel & ~BIT(0)) {
147*4882a593Smuzhiyun 		printf("Fail: read msel=%d\n", msel);
148*4882a593Smuzhiyun 		return -EPERM;
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	return 0;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun /*
155*4882a593Smuzhiyun  * Write cdratio and cdwidth based on whether the bitstream is compressed
156*4882a593Smuzhiyun  * and/or encoded
157*4882a593Smuzhiyun  */
fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width,u32 * rbf_data,size_t rbf_size)158*4882a593Smuzhiyun static int fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width, u32 *rbf_data,
159*4882a593Smuzhiyun 				       size_t rbf_size)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	unsigned int cd_ratio;
162*4882a593Smuzhiyun 	bool encrypt, compress;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	/*
165*4882a593Smuzhiyun          * According to the bitstream specification,
166*4882a593Smuzhiyun 	 * both encryption and compression status are
167*4882a593Smuzhiyun          * in location before offset 230 of the buffer.
168*4882a593Smuzhiyun          */
169*4882a593Smuzhiyun 	if (rbf_size < MIN_BITSTREAM_SIZECHECK)
170*4882a593Smuzhiyun 		return -EINVAL;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	encrypt = (rbf_data[ENCRYPTION_OFFSET] >> 2) & 3;
173*4882a593Smuzhiyun 	encrypt = encrypt != 0;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	compress = (rbf_data[COMPRESSION_OFFSET] >> 1) & 1;
176*4882a593Smuzhiyun 	compress = !compress;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	debug("header word %d = %08x\n", 69, rbf_data[69]);
179*4882a593Smuzhiyun 	debug("header word %d = %08x\n", 229, rbf_data[229]);
180*4882a593Smuzhiyun 	debug("read from rbf header: encrypt=%d compress=%d\n", encrypt, compress);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	/*
183*4882a593Smuzhiyun 	 * from the register map description of cdratio in imgcfg_ctrl_02:
184*4882a593Smuzhiyun 	 *  Normal Configuration    : 32bit Passive Parallel
185*4882a593Smuzhiyun 	 *  Partial Reconfiguration : 16bit Passive Parallel
186*4882a593Smuzhiyun 	 */
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/*
189*4882a593Smuzhiyun 	 * cd ratio is dependent on cfg width and whether the bitstream
190*4882a593Smuzhiyun 	 * is encrypted and/or compressed.
191*4882a593Smuzhiyun 	 *
192*4882a593Smuzhiyun 	 * | width | encr. | compr. | cd ratio |
193*4882a593Smuzhiyun 	 * |  16   |   0   |   0    |     1    |
194*4882a593Smuzhiyun 	 * |  16   |   0   |   1    |     4    |
195*4882a593Smuzhiyun 	 * |  16   |   1   |   0    |     2    |
196*4882a593Smuzhiyun 	 * |  16   |   1   |   1    |     4    |
197*4882a593Smuzhiyun 	 * |  32   |   0   |   0    |     1    |
198*4882a593Smuzhiyun 	 * |  32   |   0   |   1    |     8    |
199*4882a593Smuzhiyun 	 * |  32   |   1   |   0    |     4    |
200*4882a593Smuzhiyun 	 * |  32   |   1   |   1    |     8    |
201*4882a593Smuzhiyun 	 */
202*4882a593Smuzhiyun 	if (!compress && !encrypt) {
203*4882a593Smuzhiyun 		cd_ratio = CDRATIO_x1;
204*4882a593Smuzhiyun 	} else {
205*4882a593Smuzhiyun 		if (compress)
206*4882a593Smuzhiyun 			cd_ratio = CDRATIO_x4;
207*4882a593Smuzhiyun 		else
208*4882a593Smuzhiyun 			cd_ratio = CDRATIO_x2;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		/* if 32 bit, double the cd ratio (so register
211*4882a593Smuzhiyun 		   field setting is incremented) */
212*4882a593Smuzhiyun 		if (cfg_width == CFGWDTH_32)
213*4882a593Smuzhiyun 			cd_ratio += 1;
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	fpgamgr_set_cfgwdth(cfg_width);
217*4882a593Smuzhiyun 	fpgamgr_set_cd_ratio(cd_ratio);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	return 0;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
fpgamgr_reset(void)222*4882a593Smuzhiyun static int fpgamgr_reset(void)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	unsigned long reg;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	/* S2F_NCONFIG = 0 */
227*4882a593Smuzhiyun 	clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
228*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	/* Wait for f2s_nstatus == 0 */
231*4882a593Smuzhiyun 	if (wait_for_f2s_nstatus_pin(0))
232*4882a593Smuzhiyun 		return -ETIME;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	/* S2F_NCONFIG = 1 */
235*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
236*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	/* Wait for f2s_nstatus == 1 */
239*4882a593Smuzhiyun 	if (wait_for_f2s_nstatus_pin(1))
240*4882a593Smuzhiyun 		return -ETIME;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	/* read and confirm f2s_condone_pin = 0 and f2s_condone_oe = 1 */
243*4882a593Smuzhiyun 	reg = readl(&fpga_manager_base->imgcfg_stat);
244*4882a593Smuzhiyun 	if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) != 0)
245*4882a593Smuzhiyun 		return -EPERM;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_OE_SET_MSK) == 0)
248*4882a593Smuzhiyun 		return -EPERM;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	return 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun /* Start the FPGA programming by initialize the FPGA Manager */
fpgamgr_program_init(u32 * rbf_data,size_t rbf_size)254*4882a593Smuzhiyun int fpgamgr_program_init(u32 * rbf_data, size_t rbf_size)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	int ret;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	/* Step 1 */
259*4882a593Smuzhiyun 	if (fpgamgr_verify_msel())
260*4882a593Smuzhiyun 		return -EPERM;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	/* Step 2 */
263*4882a593Smuzhiyun 	if (fpgamgr_set_cdratio_cdwidth(CFGWDTH_32, rbf_data, rbf_size))
264*4882a593Smuzhiyun 		return -EPERM;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	/*
267*4882a593Smuzhiyun 	 * Step 3:
268*4882a593Smuzhiyun 	 * Make sure no other external devices are trying to interfere with
269*4882a593Smuzhiyun 	 * programming:
270*4882a593Smuzhiyun 	 */
271*4882a593Smuzhiyun 	if (wait_for_nconfig_pin_and_nstatus_pin())
272*4882a593Smuzhiyun 		return -ETIME;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	/*
275*4882a593Smuzhiyun 	 * Step 4:
276*4882a593Smuzhiyun 	 * Deassert the signal drives from HPS
277*4882a593Smuzhiyun 	 *
278*4882a593Smuzhiyun 	 * S2F_NCE = 1
279*4882a593Smuzhiyun 	 * S2F_PR_REQUEST = 0
280*4882a593Smuzhiyun 	 * EN_CFG_CTRL = 0
281*4882a593Smuzhiyun 	 * EN_CFG_DATA = 0
282*4882a593Smuzhiyun 	 * S2F_NCONFIG = 1
283*4882a593Smuzhiyun 	 * S2F_NSTATUS_OE = 0
284*4882a593Smuzhiyun 	 * S2F_CONDONE_OE = 0
285*4882a593Smuzhiyun 	 */
286*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
287*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
290*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST_SET_MSK);
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
293*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
294*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
297*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
300*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE_SET_MSK |
301*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE_SET_MSK);
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	/*
304*4882a593Smuzhiyun 	 * Step 5:
305*4882a593Smuzhiyun 	 * Enable overrides
306*4882a593Smuzhiyun 	 * S2F_NENABLE_CONFIG = 0
307*4882a593Smuzhiyun 	 * S2F_NENABLE_NCONFIG = 0
308*4882a593Smuzhiyun 	 */
309*4882a593Smuzhiyun 	clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
310*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG_SET_MSK);
311*4882a593Smuzhiyun 	clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
312*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG_SET_MSK);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	/*
315*4882a593Smuzhiyun 	 * Disable driving signals that HPS doesn't need to drive.
316*4882a593Smuzhiyun 	 * S2F_NENABLE_NSTATUS = 1
317*4882a593Smuzhiyun 	 * S2F_NENABLE_CONDONE = 1
318*4882a593Smuzhiyun 	 */
319*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
320*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS_SET_MSK |
321*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE_SET_MSK);
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	/*
324*4882a593Smuzhiyun 	 * Step 6:
325*4882a593Smuzhiyun 	 * Drive chip select S2F_NCE = 0
326*4882a593Smuzhiyun 	 */
327*4882a593Smuzhiyun 	 clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
328*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	/* Step 7 */
331*4882a593Smuzhiyun 	if (wait_for_nconfig_pin_and_nstatus_pin())
332*4882a593Smuzhiyun 		return -ETIME;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	/* Step 8 */
335*4882a593Smuzhiyun 	ret = fpgamgr_reset();
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (ret)
338*4882a593Smuzhiyun 		return ret;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/*
341*4882a593Smuzhiyun 	 * Step 9:
342*4882a593Smuzhiyun 	 * EN_CFG_CTRL and EN_CFG_DATA = 1
343*4882a593Smuzhiyun 	 */
344*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
345*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
346*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	return 0;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun /* Ensure the FPGA entering config done */
fpgamgr_program_poll_cd(void)352*4882a593Smuzhiyun static int fpgamgr_program_poll_cd(void)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun 	unsigned long reg, i;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
357*4882a593Smuzhiyun 		reg = readl(&fpga_manager_base->imgcfg_stat);
358*4882a593Smuzhiyun 		if (reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK)
359*4882a593Smuzhiyun 			return 0;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 		if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK) == 0) {
362*4882a593Smuzhiyun 			printf("nstatus == 0 while waiting for condone\n");
363*4882a593Smuzhiyun 			return -EPERM;
364*4882a593Smuzhiyun 		}
365*4882a593Smuzhiyun 	}
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	if (i == FPGA_TIMEOUT_CNT)
368*4882a593Smuzhiyun 		return -ETIME;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	return 0;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun /* Ensure the FPGA entering user mode */
fpgamgr_program_poll_usermode(void)374*4882a593Smuzhiyun static int fpgamgr_program_poll_usermode(void)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun 	unsigned long reg;
377*4882a593Smuzhiyun 	int ret = 0;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	if (fpgamgr_dclkcnt_set(0xf))
380*4882a593Smuzhiyun 		return -ETIME;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	ret = wait_for_user_mode();
383*4882a593Smuzhiyun 	if (ret < 0) {
384*4882a593Smuzhiyun 		printf("%s: Failed to enter user mode with ", __func__);
385*4882a593Smuzhiyun 		printf("error code %d\n", ret);
386*4882a593Smuzhiyun 		return ret;
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	/*
390*4882a593Smuzhiyun 	 * Step 14:
391*4882a593Smuzhiyun 	 * Stop DATA path and Dclk
392*4882a593Smuzhiyun 	 * EN_CFG_CTRL and EN_CFG_DATA = 0
393*4882a593Smuzhiyun 	 */
394*4882a593Smuzhiyun 	clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
395*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
396*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	/*
399*4882a593Smuzhiyun 	 * Step 15:
400*4882a593Smuzhiyun 	 * Disable overrides
401*4882a593Smuzhiyun 	 * S2F_NENABLE_CONFIG = 1
402*4882a593Smuzhiyun 	 * S2F_NENABLE_NCONFIG = 1
403*4882a593Smuzhiyun 	 */
404*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
405*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG_SET_MSK);
406*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
407*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG_SET_MSK);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	/* Disable chip select S2F_NCE = 1 */
410*4882a593Smuzhiyun 	setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
411*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	/*
414*4882a593Smuzhiyun 	 * Step 16:
415*4882a593Smuzhiyun 	 * Final check
416*4882a593Smuzhiyun 	 */
417*4882a593Smuzhiyun 	reg = readl(&fpga_manager_base->imgcfg_stat);
418*4882a593Smuzhiyun 	if (((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) !=
419*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) ||
420*4882a593Smuzhiyun 	    ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) !=
421*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) ||
422*4882a593Smuzhiyun 	    ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK) !=
423*4882a593Smuzhiyun 		ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK))
424*4882a593Smuzhiyun 		return -EPERM;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	return 0;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
fpgamgr_program_finish(void)429*4882a593Smuzhiyun int fpgamgr_program_finish(void)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	/* Ensure the FPGA entering config done */
432*4882a593Smuzhiyun 	int status = fpgamgr_program_poll_cd();
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	if (status) {
435*4882a593Smuzhiyun 		printf("FPGA: Poll CD failed with error code %d\n", status);
436*4882a593Smuzhiyun 		return -EPERM;
437*4882a593Smuzhiyun 	}
438*4882a593Smuzhiyun 	WATCHDOG_RESET();
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	/* Ensure the FPGA entering user mode */
441*4882a593Smuzhiyun 	status = fpgamgr_program_poll_usermode();
442*4882a593Smuzhiyun 	if (status) {
443*4882a593Smuzhiyun 		printf("FPGA: Poll usermode failed with error code %d\n",
444*4882a593Smuzhiyun 			status);
445*4882a593Smuzhiyun 		return -EPERM;
446*4882a593Smuzhiyun 	}
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	printf("Full Configuration Succeeded.\n");
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	return 0;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun /*
454*4882a593Smuzhiyun  * FPGA Manager to program the FPGA. This is the interface used by FPGA driver.
455*4882a593Smuzhiyun  * Return 0 for sucess, non-zero for error.
456*4882a593Smuzhiyun  */
socfpga_load(Altera_desc * desc,const void * rbf_data,size_t rbf_size)457*4882a593Smuzhiyun int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun 	unsigned long status;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	/* disable all signals from hps peripheral controller to fpga */
462*4882a593Smuzhiyun 	writel(0, &system_manager_base->fpgaintf_en_global);
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	/* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
465*4882a593Smuzhiyun 	socfpga_bridges_reset();
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	/* Initialize the FPGA Manager */
468*4882a593Smuzhiyun 	status = fpgamgr_program_init((u32 *)rbf_data, rbf_size);
469*4882a593Smuzhiyun 	if (status)
470*4882a593Smuzhiyun 		return status;
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	/* Write the RBF data to FPGA Manager */
473*4882a593Smuzhiyun 	fpgamgr_program_write(rbf_data, rbf_size);
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	return fpgamgr_program_finish();
476*4882a593Smuzhiyun }
477