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