]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
f0ff4692 SR |
2 | /* |
3 | * (C) Copyright 2006 | |
4 | * Heiko Schocher, [email protected] | |
5 | * Based on ACE1XK.c | |
f0ff4692 SR |
6 | */ |
7 | ||
29e58112 AD |
8 | #define LOG_CATEGORY UCLASS_FPGA |
9 | ||
03de305e | 10 | #include <config.h> /* core U-Boot definitions */ |
29e58112 | 11 | #include <log.h> |
03de305e | 12 | #include <time.h> |
f0ff4692 SR |
13 | #include <altera.h> |
14 | #include <ACEX1K.h> /* ACEX device family */ | |
c05ed00a | 15 | #include <linux/delay.h> |
f0ff4692 | 16 | |
f0ff4692 SR |
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). | |
72fc2645 | 19 | * If there is a need to operate slower, define CFG_FPGA_DELAY in |
f0ff4692 SR |
20 | * the board config file to slow things down. |
21 | */ | |
72fc2645 TR |
22 | #ifndef CFG_FPGA_DELAY |
23 | #define CFG_FPGA_DELAY() | |
f0ff4692 SR |
24 | #endif |
25 | ||
65cc0e2a TR |
26 | #ifndef CFG_SYS_FPGA_WAIT |
27 | #define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ / 10 /* 100 ms */ | |
f0ff4692 SR |
28 | #endif |
29 | ||
e6a857da WD |
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); | |
f0ff4692 | 32 | /* static int CYC2_ps_info( Altera_desc *desc ); */ |
f0ff4692 SR |
33 | |
34 | /* ------------------------------------------------------------------------- */ | |
35 | /* CYCLON2 Generic Implementation */ | |
e6a857da | 36 | int CYC2_load(Altera_desc *desc, const void *buf, size_t bsize) |
f0ff4692 SR |
37 | { |
38 | int ret_val = FPGA_FAIL; | |
39 | ||
40 | switch (desc->iface) { | |
41 | case passive_serial: | |
29e58112 | 42 | log_debug("Launching Passive Serial Loader\n"); |
bb2c0fa0 | 43 | ret_val = CYC2_ps_load(desc, buf, bsize); |
f0ff4692 SR |
44 | break; |
45 | ||
ee44fb29 MJ |
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 | */ | |
29e58112 | 51 | log_debug("Launching Fast Passive Parallel Loader\n"); |
ee44fb29 MJ |
52 | ret_val = CYC2_ps_load(desc, buf, bsize); |
53 | break; | |
54 | ||
f0ff4692 SR |
55 | /* Add new interface types here */ |
56 | ||
57 | default: | |
bb2c0fa0 AD |
58 | printf("%s: Unsupported interface type, %d\n", |
59 | __func__, desc->iface); | |
f0ff4692 SR |
60 | } |
61 | ||
62 | return ret_val; | |
63 | } | |
64 | ||
e6a857da | 65 | int CYC2_dump(Altera_desc *desc, const void *buf, size_t bsize) |
f0ff4692 SR |
66 | { |
67 | int ret_val = FPGA_FAIL; | |
68 | ||
69 | switch (desc->iface) { | |
70 | case passive_serial: | |
29e58112 | 71 | log_debug("Launching Passive Serial Dump\n"); |
bb2c0fa0 | 72 | ret_val = CYC2_ps_dump(desc, buf, bsize); |
f0ff4692 SR |
73 | break; |
74 | ||
75 | /* Add new interface types here */ | |
76 | ||
77 | default: | |
bb2c0fa0 AD |
78 | printf("%s: Unsupported interface type, %d\n", |
79 | __func__, desc->iface); | |
f0ff4692 SR |
80 | } |
81 | ||
82 | return ret_val; | |
83 | } | |
84 | ||
bb2c0fa0 | 85 | int CYC2_info(Altera_desc *desc) |
f0ff4692 SR |
86 | { |
87 | return FPGA_SUCCESS; | |
88 | } | |
89 | ||
f0ff4692 | 90 | /* ------------------------------------------------------------------------- */ |
bb2c0fa0 | 91 | /* CYCLON2 Passive Serial Generic Implementation */ |
e6a857da | 92 | static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize) |
f0ff4692 SR |
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 | ||
29e58112 | 98 | log_debug("start with interface functions @ 0x%p\n", fn); |
f0ff4692 SR |
99 | |
100 | if (fn) { | |
101 | int cookie = desc->cookie; /* make a local copy */ | |
102 | unsigned long ts; /* timestamp */ | |
103 | ||
29e58112 AD |
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); | |
6d0f6bcf | 113 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
bb2c0fa0 | 114 | printf("Loading FPGA Device %d...", cookie); |
f0ff4692 SR |
115 | #endif |
116 | ||
117 | /* | |
118 | * Run the pre configuration function if there is one. | |
119 | */ | |
bb2c0fa0 | 120 | if (*fn->pre) |
f0ff4692 | 121 | (*fn->pre) (cookie); |
f0ff4692 SR |
122 | |
123 | /* Establish the initial state */ | |
472d5460 | 124 | (*fn->config) (false, true, cookie); /* De-assert nCONFIG */ |
a99c040c | 125 | udelay(100); |
472d5460 | 126 | (*fn->config) (true, true, cookie); /* Assert nCONFIG */ |
f0ff4692 SR |
127 | |
128 | udelay(2); /* T_cfg > 2us */ | |
129 | ||
130 | /* Wait for nSTATUS to be asserted */ | |
bb2c0fa0 | 131 | ts = get_timer(0); /* get current time */ |
f0ff4692 | 132 | do { |
72fc2645 | 133 | CFG_FPGA_DELAY(); |
65cc0e2a | 134 | if (get_timer(ts) > CFG_SYS_FPGA_WAIT) { |
bb2c0fa0 AD |
135 | /* check the time */ |
136 | puts("** Timeout waiting for STATUS to go high.\n"); | |
f0ff4692 SR |
137 | (*fn->abort) (cookie); |
138 | return FPGA_FAIL; | |
139 | } | |
140 | } while (!(*fn->status) (cookie)); | |
141 | ||
142 | /* Get ready for the burn */ | |
72fc2645 | 143 | CFG_FPGA_DELAY(); |
f0ff4692 | 144 | |
472d5460 | 145 | ret = (*fn->write) (buf, bsize, true, cookie); |
f0ff4692 | 146 | if (ret) { |
bb2c0fa0 | 147 | puts("** Write failed.\n"); |
f0ff4692 SR |
148 | (*fn->abort) (cookie); |
149 | return FPGA_FAIL; | |
150 | } | |
6d0f6bcf | 151 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
f0ff4692 SR |
152 | puts(" OK? ..."); |
153 | #endif | |
154 | ||
72fc2645 | 155 | CFG_FPGA_DELAY(); |
f0ff4692 | 156 | |
6d0f6bcf | 157 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
bb2c0fa0 | 158 | putc(' '); /* terminate the dotted line */ |
f0ff4692 SR |
159 | #endif |
160 | ||
3911b19c AD |
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 | } | |
6d0f6bcf | 170 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
3911b19c | 171 | puts(" OK\n"); |
f0ff4692 SR |
172 | #endif |
173 | ||
3911b19c | 174 | ret_val = FPGA_SUCCESS; |
f0ff4692 | 175 | |
6d0f6bcf | 176 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
3911b19c AD |
177 | if (ret_val == FPGA_SUCCESS) |
178 | puts("Done.\n"); | |
179 | else | |
180 | puts("Fail.\n"); | |
f0ff4692 | 181 | #endif |
f0ff4692 | 182 | |
b283d6ba AD |
183 | /* |
184 | * Run the post configuration function if there is one. | |
185 | */ | |
186 | if (*fn->post) | |
187 | (*fn->post) (cookie); | |
f0ff4692 | 188 | } else { |
bb2c0fa0 | 189 | printf("%s: NULL Interface function table!\n", __func__); |
f0ff4692 SR |
190 | } |
191 | ||
192 | return ret_val; | |
193 | } | |
194 | ||
e6a857da | 195 | static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize) |
f0ff4692 SR |
196 | { |
197 | /* Readback is only available through the Slave Parallel and */ | |
198 | /* boundary-scan interfaces. */ | |
bb2c0fa0 | 199 | printf("%s: Passive Serial Dumping is unavailable\n", __func__); |
f0ff4692 SR |
200 | return FPGA_FAIL; |
201 | } |