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