1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2006
4  * Heiko Schocher, hs@denx.de
5  * Based on ACE1XK.c
6  */
7 
8 #define LOG_CATEGORY UCLASS_FPGA
9 
10 #include <config.h>		/* core U-Boot definitions */
11 #include <log.h>
12 #include <time.h>
13 #include <altera.h>
14 #include <ACEX1K.h>		/* ACEX device family */
15 #include <linux/delay.h>
16 
17 /* Note: The assumption is that we cannot possibly run fast enough to
18  * overrun the device (the Slave Parallel mode can free run at 50MHz).
19  * If there is a need to operate slower, define CFG_FPGA_DELAY in
20  * the board config file to slow things down.
21  */
22 #ifndef CFG_FPGA_DELAY
23 #define CFG_FPGA_DELAY()
24 #endif
25 
26 #ifndef CFG_SYS_FPGA_WAIT
27 #define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ / 10		/* 100 ms */
28 #endif
29 
30 static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize);
31 static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
32 /* static int CYC2_ps_info( Altera_desc *desc ); */
33 
34 /* ------------------------------------------------------------------------- */
35 /* CYCLON2 Generic Implementation */
CYC2_load(Altera_desc * desc,const void * buf,size_t bsize)36 int CYC2_load(Altera_desc *desc, const void *buf, size_t bsize)
37 {
38 	int ret_val = FPGA_FAIL;
39 
40 	switch (desc->iface) {
41 	case passive_serial:
42 		log_debug("Launching Passive Serial Loader\n");
43 		ret_val = CYC2_ps_load(desc, buf, bsize);
44 		break;
45 
46 	case fast_passive_parallel:
47 		/* Fast Passive Parallel (FPP) and PS only differ in what is
48 		 * done in the write() callback. Use the existing PS load
49 		 * function for FPP, too.
50 		 */
51 		log_debug("Launching Fast Passive Parallel Loader\n");
52 		ret_val = CYC2_ps_load(desc, buf, bsize);
53 		break;
54 
55 		/* Add new interface types here */
56 
57 	default:
58 		printf("%s: Unsupported interface type, %d\n",
59 		       __func__, desc->iface);
60 	}
61 
62 	return ret_val;
63 }
64 
CYC2_dump(Altera_desc * desc,const void * buf,size_t bsize)65 int CYC2_dump(Altera_desc *desc, const void *buf, size_t bsize)
66 {
67 	int ret_val = FPGA_FAIL;
68 
69 	switch (desc->iface) {
70 	case passive_serial:
71 		log_debug("Launching Passive Serial Dump\n");
72 		ret_val = CYC2_ps_dump(desc, buf, bsize);
73 		break;
74 
75 		/* Add new interface types here */
76 
77 	default:
78 		printf("%s: Unsupported interface type, %d\n",
79 		       __func__, desc->iface);
80 	}
81 
82 	return ret_val;
83 }
84 
CYC2_info(Altera_desc * desc)85 int CYC2_info(Altera_desc *desc)
86 {
87 	return FPGA_SUCCESS;
88 }
89 
90 /* ------------------------------------------------------------------------- */
91 /* CYCLON2 Passive Serial Generic Implementation                             */
CYC2_ps_load(Altera_desc * desc,const void * buf,size_t bsize)92 static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize)
93 {
94 	int ret_val = FPGA_FAIL;	/* assume the worst */
95 	Altera_CYC2_Passive_Serial_fns *fn = desc->iface_fns;
96 	int	ret = 0;
97 
98 	log_debug("start with interface functions @ 0x%p\n", fn);
99 
100 	if (fn) {
101 		int cookie = desc->cookie;	/* make a local copy */
102 		unsigned long ts;		/* timestamp */
103 
104 		log_debug("Function Table:\n"
105 			  "ptr:\t0x%p\n"
106 			  "struct: 0x%p\n"
107 			  "config:\t0x%p\n"
108 			  "status:\t0x%p\n"
109 			  "write:\t0x%p\n"
110 			  "done:\t0x%p\n\n",
111 			  &fn, fn, fn->config, fn->status,
112 			  fn->write, fn->done);
113 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
114 		printf("Loading FPGA Device %d...", cookie);
115 #endif
116 
117 		/*
118 		 * Run the pre configuration function if there is one.
119 		 */
120 		if (*fn->pre)
121 			(*fn->pre) (cookie);
122 
123 		/* Establish the initial state */
124 		(*fn->config) (false, true, cookie);	/* De-assert nCONFIG */
125 		udelay(100);
126 		(*fn->config) (true, true, cookie);	/* Assert nCONFIG */
127 
128 		udelay(2);		/* T_cfg > 2us	*/
129 
130 		/* Wait for nSTATUS to be asserted */
131 		ts = get_timer(0);		/* get current time */
132 		do {
133 			CFG_FPGA_DELAY();
134 			if (get_timer(ts) > CFG_SYS_FPGA_WAIT) {
135 				/* check the time */
136 				puts("** Timeout waiting for STATUS to go high.\n");
137 				(*fn->abort) (cookie);
138 				return FPGA_FAIL;
139 			}
140 		} while (!(*fn->status) (cookie));
141 
142 		/* Get ready for the burn */
143 		CFG_FPGA_DELAY();
144 
145 		ret = (*fn->write) (buf, bsize, true, cookie);
146 		if (ret) {
147 			puts("** Write failed.\n");
148 			(*fn->abort) (cookie);
149 			return FPGA_FAIL;
150 		}
151 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
152 		puts(" OK? ...");
153 #endif
154 
155 		CFG_FPGA_DELAY();
156 
157 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
158 		putc(' ');			/* terminate the dotted line */
159 #endif
160 
161 		/*
162 		 * Checking FPGA's CONF_DONE signal - correctly booted ?
163 		 */
164 
165 		if (!(*fn->done) (cookie)) {
166 			puts("** Booting failed! CONF_DONE is still deasserted.\n");
167 			(*fn->abort) (cookie);
168 			return FPGA_FAIL;
169 		}
170 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
171 		puts(" OK\n");
172 #endif
173 
174 		ret_val = FPGA_SUCCESS;
175 
176 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
177 		if (ret_val == FPGA_SUCCESS)
178 			puts("Done.\n");
179 		else
180 			puts("Fail.\n");
181 #endif
182 
183 		/*
184 		 * Run the post configuration function if there is one.
185 		 */
186 		if (*fn->post)
187 			(*fn->post) (cookie);
188 	} else {
189 		printf("%s: NULL Interface function table!\n", __func__);
190 	}
191 
192 	return ret_val;
193 }
194 
CYC2_ps_dump(Altera_desc * desc,const void * buf,size_t bsize)195 static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize)
196 {
197 	/* Readback is only available through the Slave Parallel and         */
198 	/* boundary-scan interfaces.                                         */
199 	printf("%s: Passive Serial Dumping is unavailable\n", __func__);
200 	return FPGA_FAIL;
201 }
202