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