1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2003
4  * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
5  *
6  * (C) Copyright 2002
7  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
8  */
9 
10 #define LOG_CATEGORY UCLASS_FPGA
11 
12 #include <common.h>		/* core U-Boot definitions */
13 #include <console.h>
14 #include <log.h>
15 #include <ACEX1K.h>		/* ACEX device family */
16 #include <linux/delay.h>
17 
18 /* Note: The assumption is that we cannot possibly run fast enough to
19  * overrun the device (the Slave Parallel mode can free run at 50MHz).
20  * If there is a need to operate slower, define CFG_FPGA_DELAY in
21  * the board config file to slow things down.
22  */
23 #ifndef CFG_FPGA_DELAY
24 #define CFG_FPGA_DELAY()
25 #endif
26 
27 #ifndef CFG_SYS_FPGA_WAIT
28 #define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ/10		/* 100 ms */
29 #endif
30 
31 static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize);
32 static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
33 /* static int ACEX1K_ps_info(Altera_desc *desc); */
34 
35 /* ------------------------------------------------------------------------- */
36 /* ACEX1K Generic Implementation */
ACEX1K_load(Altera_desc * desc,const void * buf,size_t bsize)37 int ACEX1K_load(Altera_desc *desc, const void *buf, size_t bsize)
38 {
39 	int ret_val = FPGA_FAIL;
40 
41 	switch (desc->iface) {
42 	case passive_serial:
43 		log_debug("Launching Passive Serial Loader\n");
44 		ret_val = ACEX1K_ps_load (desc, buf, bsize);
45 		break;
46 
47 		/* Add new interface types here */
48 
49 	default:
50 		printf ("%s: Unsupported interface type, %d\n",
51 				__FUNCTION__, desc->iface);
52 	}
53 
54 	return ret_val;
55 }
56 
ACEX1K_dump(Altera_desc * desc,const void * buf,size_t bsize)57 int ACEX1K_dump(Altera_desc *desc, const void *buf, size_t bsize)
58 {
59 	int ret_val = FPGA_FAIL;
60 
61 	switch (desc->iface) {
62 	case passive_serial:
63 		log_debug("Launching Passive Serial Dump\n");
64 		ret_val = ACEX1K_ps_dump (desc, buf, bsize);
65 		break;
66 
67 		/* Add new interface types here */
68 
69 	default:
70 		printf ("%s: Unsupported interface type, %d\n",
71 				__FUNCTION__, desc->iface);
72 	}
73 
74 	return ret_val;
75 }
76 
ACEX1K_info(Altera_desc * desc)77 int ACEX1K_info( Altera_desc *desc )
78 {
79 	return FPGA_SUCCESS;
80 }
81 
82 
83 /* ------------------------------------------------------------------------- */
84 /* ACEX1K Passive Serial Generic Implementation                                  */
85 
ACEX1K_ps_load(Altera_desc * desc,const void * buf,size_t bsize)86 static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize)
87 {
88 	int ret_val = FPGA_FAIL;	/* assume the worst */
89 	Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns;
90 	int i;
91 
92 	log_debug("start with interface functions @ 0x%p\n", fn);
93 
94 	if (fn) {
95 		size_t bytecount = 0;
96 		unsigned char *data = (unsigned char *) buf;
97 		int cookie = desc->cookie;	/* make a local copy */
98 		unsigned long ts;		/* timestamp */
99 
100 		log_debug("Function Table:\n"
101 			  "ptr:\t0x%p\n"
102 			  "struct: 0x%p\n"
103 			  "config:\t0x%p\n"
104 			  "status:\t0x%p\n"
105 			  "clk:\t0x%p\n"
106 			  "data:\t0x%p\n"
107 			  "done:\t0x%p\n\n",
108 			  &fn, fn, fn->config, fn->status,
109 			  fn->clk, fn->data, fn->done);
110 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
111 		printf ("Loading FPGA Device %d...", cookie);
112 #endif
113 
114 		/*
115 		 * Run the pre configuration function if there is one.
116 		 */
117 		if (*fn->pre) {
118 			(*fn->pre) (cookie);
119 		}
120 
121 		/* Establish the initial state */
122 		(*fn->config) (true, true, cookie);	/* Assert nCONFIG */
123 
124 		udelay(2);		/* T_cfg > 2us	*/
125 
126 		/* nSTATUS should be asserted now */
127 		(*fn->done) (cookie);
128 		if ( !(*fn->status) (cookie) ) {
129 			puts ("** nSTATUS is not asserted.\n");
130 			(*fn->abort) (cookie);
131 			return FPGA_FAIL;
132 		}
133 
134 		(*fn->config) (false, true, cookie);	/* Deassert nCONFIG */
135 		udelay(2);		/* T_cf2st1 < 4us	*/
136 
137 		/* Wait for nSTATUS to be released (i.e. deasserted) */
138 		ts = get_timer (0);		/* get current time */
139 		do {
140 			CFG_FPGA_DELAY ();
141 			if (get_timer (ts) > CFG_SYS_FPGA_WAIT) {	/* check the time */
142 				puts ("** Timeout waiting for STATUS to go high.\n");
143 				(*fn->abort) (cookie);
144 				return FPGA_FAIL;
145 			}
146 			(*fn->done) (cookie);
147 		} while ((*fn->status) (cookie));
148 
149 		/* Get ready for the burn */
150 		CFG_FPGA_DELAY ();
151 
152 		/* Load the data */
153 		while (bytecount < bsize) {
154 			unsigned char val=0;
155 #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
156 			if (ctrlc ()) {
157 				(*fn->abort) (cookie);
158 				return FPGA_FAIL;
159 			}
160 #endif
161 			/* Altera detects an error if INIT goes low (active)
162 			   while DONE is low (inactive) */
163 #if 0 /* not yet implemented */
164 			if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
165 				puts ("** CRC error during FPGA load.\n");
166 				(*fn->abort) (cookie);
167 				return (FPGA_FAIL);
168 			}
169 #endif
170 			val = data [bytecount ++ ];
171 			i = 8;
172 			do {
173 				/* Deassert the clock */
174 				(*fn->clk) (false, true, cookie);
175 				CFG_FPGA_DELAY ();
176 				/* Write data */
177 				(*fn->data) ((val & 0x01), true, cookie);
178 				CFG_FPGA_DELAY ();
179 				/* Assert the clock */
180 				(*fn->clk) (true, true, cookie);
181 				CFG_FPGA_DELAY ();
182 				val >>= 1;
183 				i --;
184 			} while (i > 0);
185 
186 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
187 			if (bytecount % (bsize / 40) == 0)
188 				putc ('.');		/* let them know we are alive */
189 #endif
190 		}
191 
192 		CFG_FPGA_DELAY ();
193 
194 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
195 		putc (' ');			/* terminate the dotted line */
196 #endif
197 
198 	/*
199 	 * Checking FPGA's CONF_DONE signal - correctly booted ?
200 	 */
201 
202 	if ( ! (*fn->done) (cookie) ) {
203 		puts ("** Booting failed! CONF_DONE is still deasserted.\n");
204 		(*fn->abort) (cookie);
205 		return (FPGA_FAIL);
206 	}
207 
208 	/*
209 	 * "DCLK must be clocked an additional 10 times fpr ACEX 1K..."
210 	 */
211 
212 	for (i = 0; i < 12; i++) {
213 		CFG_FPGA_DELAY ();
214 		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
215 		CFG_FPGA_DELAY ();
216 		(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
217 	}
218 
219 	ret_val = FPGA_SUCCESS;
220 
221 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
222 		if (ret_val == FPGA_SUCCESS) {
223 			puts ("Done.\n");
224 		}
225 		else {
226 			puts ("Fail.\n");
227 		}
228 #endif
229 	(*fn->post) (cookie);
230 
231 	} else {
232 		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
233 	}
234 
235 	return ret_val;
236 }
237 
ACEX1K_ps_dump(Altera_desc * desc,const void * buf,size_t bsize)238 static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize)
239 {
240 	/* Readback is only available through the Slave Parallel and         */
241 	/* boundary-scan interfaces.                                         */
242 	printf ("%s: Passive Serial Dumping is unavailable\n",
243 			__FUNCTION__);
244 	return FPGA_FAIL;
245 }
246