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