]>
Commit | Line | Data |
---|---|---|
255ef4d9 DE |
1 | /* |
2 | * (C) Copyright 2010 | |
3 | * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de | |
4 | * | |
5 | * based on kilauea.c | |
6 | * by Stefan Roese, DENX Software Engineering, sr@denx.de. | |
7 | * | |
8 | * See file CREDITS for list of people who contributed to this | |
9 | * project. | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU General Public License as | |
13 | * published by the Free Software Foundation; either version 2 of | |
14 | * the License, or (at your option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
22 | * along with this program; if not, write to the Free Software | |
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
24 | * MA 02111-1307 USA | |
25 | */ | |
26 | ||
27 | #include <common.h> | |
28 | #include <asm/ppc4xx.h> | |
29 | #include <asm/ppc405.h> | |
30 | #include <libfdt.h> | |
31 | #include <fdt_support.h> | |
32 | #include <asm/processor.h> | |
33 | #include <asm/io.h> | |
34 | #include <asm/errno.h> | |
35 | #include <asm/ppc4xx-gpio.h> | |
36 | #include <flash.h> | |
37 | ||
38 | #include <pca9698.h> | |
39 | ||
40 | #include "405ex.h" | |
41 | #include <gdsys_fpga.h> | |
42 | ||
43 | #include <miiphy.h> | |
44 | #include <i2c.h> | |
45 | #include <dtt.h> | |
46 | ||
47 | DECLARE_GLOBAL_DATA_PTR; | |
48 | ||
49 | #define PHYREG_CONTROL 0 | |
50 | #define PHYREG_PAGE_ADDRESS 22 | |
51 | #define PHYREG_PG0_COPPER_SPECIFIC_CONTROL_1 16 | |
52 | #define PHYREG_PG2_COPPER_SPECIFIC_CONTROL_2 26 | |
53 | #define PHYREG_PG2_MAC_SPECIFIC_STATUS_1 17 | |
54 | #define PHYREG_PG2_MAC_SPECIFIC_CONTROL 21 | |
55 | ||
56 | #define LATCH0_BASE (CONFIG_SYS_LATCH_BASE) | |
57 | #define LATCH1_BASE (CONFIG_SYS_LATCH_BASE + 0x100) | |
58 | #define LATCH2_BASE (CONFIG_SYS_LATCH_BASE + 0x200) | |
59 | #define LATCH3_BASE (CONFIG_SYS_LATCH_BASE + 0x300) | |
60 | ||
61 | enum { | |
62 | UNITTYPE_CCD_SWITCH = 1, | |
63 | }; | |
64 | ||
65 | enum { | |
66 | HWVER_100 = 0, | |
67 | HWVER_110 = 1, | |
68 | }; | |
69 | ||
70 | static inline void blank_string(int size) | |
71 | { | |
72 | int i; | |
73 | ||
74 | for (i = 0; i < size; i++) | |
75 | putc('\b'); | |
76 | for (i = 0; i < size; i++) | |
77 | putc(' '); | |
78 | for (i = 0; i < size; i++) | |
79 | putc('\b'); | |
80 | } | |
81 | ||
82 | /* | |
83 | * Board early initialization function | |
84 | */ | |
85 | int misc_init_r(void) | |
86 | { | |
87 | /* startup fans */ | |
88 | dtt_init(); | |
89 | ||
90 | #ifdef CONFIG_ENV_IS_IN_FLASH | |
91 | /* Monitor protection ON by default */ | |
92 | flash_protect(FLAG_PROTECT_SET, | |
93 | -CONFIG_SYS_MONITOR_LEN, | |
94 | 0xffffffff, | |
95 | &flash_info[0]); | |
96 | #endif | |
97 | ||
98 | return 0; | |
99 | } | |
100 | ||
101 | static void print_fpga_info(unsigned dev) | |
102 | { | |
0e60aa85 | 103 | struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(dev); |
255ef4d9 DE |
104 | u16 versions = in_le16(&fpga->versions); |
105 | u16 fpga_version = in_le16(&fpga->fpga_version); | |
106 | u16 fpga_features = in_le16(&fpga->fpga_features); | |
107 | int fpga_state = get_fpga_state(dev); | |
108 | ||
109 | unsigned unit_type; | |
110 | unsigned hardware_version; | |
111 | unsigned feature_channels; | |
112 | unsigned feature_expansion; | |
113 | ||
114 | printf("FPGA%d: ", dev); | |
115 | if (fpga_state & FPGA_STATE_PLATFORM) | |
116 | printf("(legacy) "); | |
117 | ||
118 | if (fpga_state & FPGA_STATE_DONE_FAILED) { | |
119 | printf(" done timed out\n"); | |
120 | return; | |
121 | } | |
122 | ||
123 | if (fpga_state & FPGA_STATE_REFLECTION_FAILED) { | |
124 | printf(" refelectione test failed\n"); | |
125 | return; | |
126 | } | |
127 | ||
128 | unit_type = (versions & 0xf000) >> 12; | |
129 | hardware_version = versions & 0x000f; | |
130 | feature_channels = fpga_features & 0x007f; | |
131 | feature_expansion = fpga_features & (1<<15); | |
132 | ||
133 | switch (unit_type) { | |
134 | case UNITTYPE_CCD_SWITCH: | |
135 | printf("CCD-Switch"); | |
136 | break; | |
137 | ||
138 | default: | |
139 | printf("UnitType %d(not supported)", unit_type); | |
140 | break; | |
141 | } | |
142 | ||
143 | switch (hardware_version) { | |
144 | case HWVER_100: | |
145 | printf(" HW-Ver 1.00\n"); | |
146 | break; | |
147 | ||
148 | case HWVER_110: | |
149 | printf(" HW-Ver 1.10\n"); | |
150 | break; | |
151 | ||
152 | default: | |
153 | printf(" HW-Ver %d(not supported)\n", | |
154 | hardware_version); | |
155 | break; | |
156 | } | |
157 | ||
158 | printf(" FPGA V %d.%02d, features:", | |
159 | fpga_version / 100, fpga_version % 100); | |
160 | ||
161 | printf(" %d channel(s)", feature_channels); | |
162 | ||
163 | printf(", expansion %ssupported\n", feature_expansion ? "" : "un"); | |
164 | } | |
165 | ||
166 | int checkboard(void) | |
167 | { | |
168 | char *s = getenv("serial#"); | |
169 | ||
170 | printf("Board: CATCenter Io64\n"); | |
171 | ||
172 | if (s != NULL) { | |
173 | puts(", serial# "); | |
174 | puts(s); | |
175 | } | |
176 | ||
177 | return 0; | |
178 | } | |
179 | ||
180 | int configure_gbit_phy(char *bus, unsigned char addr) | |
181 | { | |
182 | unsigned short value; | |
183 | ||
184 | /* select page 0 */ | |
185 | if (miiphy_write(bus, addr, PHYREG_PAGE_ADDRESS, 0x0000)) | |
186 | goto err_out; | |
187 | /* switch to powerdown */ | |
188 | if (miiphy_read(bus, addr, PHYREG_PG0_COPPER_SPECIFIC_CONTROL_1, | |
189 | &value)) | |
190 | goto err_out; | |
191 | if (miiphy_write(bus, addr, PHYREG_PG0_COPPER_SPECIFIC_CONTROL_1, | |
192 | value | 0x0004)) | |
193 | goto err_out; | |
194 | /* select page 2 */ | |
195 | if (miiphy_write(bus, addr, PHYREG_PAGE_ADDRESS, 0x0002)) | |
196 | goto err_out; | |
197 | /* disable SGMII autonegotiation */ | |
198 | if (miiphy_write(bus, addr, PHYREG_PG2_MAC_SPECIFIC_CONTROL, 48)) | |
199 | goto err_out; | |
200 | /* select page 0 */ | |
201 | if (miiphy_write(bus, addr, PHYREG_PAGE_ADDRESS, 0x0000)) | |
202 | goto err_out; | |
203 | /* switch from powerdown to normal operation */ | |
204 | if (miiphy_read(bus, addr, PHYREG_PG0_COPPER_SPECIFIC_CONTROL_1, | |
205 | &value)) | |
206 | goto err_out; | |
207 | if (miiphy_write(bus, addr, PHYREG_PG0_COPPER_SPECIFIC_CONTROL_1, | |
208 | value & ~0x0004)) | |
209 | goto err_out; | |
210 | /* reset phy so settings take effect */ | |
211 | if (miiphy_write(bus, addr, PHYREG_CONTROL, 0x9140)) | |
212 | goto err_out; | |
213 | ||
214 | return 0; | |
215 | ||
216 | err_out: | |
217 | printf("Error writing to the PHY addr=%02x\n", addr); | |
218 | return -1; | |
219 | } | |
220 | ||
221 | int verify_gbit_phy(char *bus, unsigned char addr) | |
222 | { | |
223 | unsigned short value; | |
224 | ||
225 | /* select page 2 */ | |
226 | if (miiphy_write(bus, addr, PHYREG_PAGE_ADDRESS, 0x0002)) | |
227 | goto err_out; | |
228 | /* verify SGMII link status */ | |
229 | if (miiphy_read(bus, addr, PHYREG_PG2_MAC_SPECIFIC_STATUS_1, &value)) | |
230 | goto err_out; | |
231 | if (!(value & (1 << 10))) | |
232 | return -2; | |
233 | ||
234 | return 0; | |
235 | ||
236 | err_out: | |
237 | printf("Error writing to the PHY addr=%02x\n", addr); | |
238 | return -1; | |
239 | } | |
240 | ||
241 | int last_stage_init(void) | |
242 | { | |
243 | unsigned int k; | |
244 | unsigned int fpga; | |
0e60aa85 DE |
245 | struct ihs_fpga *fpga0 = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0); |
246 | struct ihs_fpga *fpga1 = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(1); | |
255ef4d9 DE |
247 | int failed = 0; |
248 | char str_phys[] = "Setup PHYs -"; | |
249 | char str_serdes[] = "Start SERDES blocks"; | |
250 | char str_channels[] = "Start FPGA channels"; | |
251 | char str_locks[] = "Verify SERDES locks"; | |
06b17412 | 252 | char str_hicb[] = "Verify HICB status"; |
255ef4d9 DE |
253 | char str_status[] = "Verify PHY status -"; |
254 | char slash[] = "\\|/-\\|/-"; | |
255 | ||
256 | print_fpga_info(0); | |
257 | print_fpga_info(1); | |
258 | ||
259 | /* setup Gbit PHYs */ | |
260 | puts("TRANS: "); | |
261 | puts(str_phys); | |
262 | miiphy_register(CONFIG_SYS_GBIT_MII_BUSNAME, | |
263 | bb_miiphy_read, bb_miiphy_write); | |
264 | ||
265 | for (k = 0; k < 32; ++k) { | |
266 | configure_gbit_phy(CONFIG_SYS_GBIT_MII_BUSNAME, k); | |
267 | putc('\b'); | |
268 | putc(slash[k % 8]); | |
269 | } | |
270 | ||
271 | miiphy_register(CONFIG_SYS_GBIT_MII1_BUSNAME, | |
272 | bb_miiphy_read, bb_miiphy_write); | |
273 | ||
274 | for (k = 0; k < 32; ++k) { | |
275 | configure_gbit_phy(CONFIG_SYS_GBIT_MII1_BUSNAME, k); | |
276 | putc('\b'); | |
277 | putc(slash[k % 8]); | |
278 | } | |
279 | blank_string(strlen(str_phys)); | |
280 | ||
281 | /* take fpga serdes blocks out of reset */ | |
282 | puts(str_serdes); | |
283 | udelay(500000); | |
284 | out_le16(&fpga0->quad_serdes_reset, 0); | |
285 | out_le16(&fpga1->quad_serdes_reset, 0); | |
286 | blank_string(strlen(str_serdes)); | |
287 | ||
288 | /* take channels out of reset */ | |
289 | puts(str_channels); | |
290 | udelay(500000); | |
291 | for (fpga = 0; fpga < 2; ++fpga) { | |
292 | u16 *ch0_config_int = &(fpga ? fpga1 : fpga0)->ch0_config_int; | |
293 | for (k = 0; k < 32; ++k) | |
294 | out_le16(ch0_config_int + 4 * k, 0); | |
295 | } | |
296 | blank_string(strlen(str_channels)); | |
297 | ||
298 | /* verify channels serdes lock */ | |
299 | puts(str_locks); | |
300 | udelay(500000); | |
301 | for (fpga = 0; fpga < 2; ++fpga) { | |
302 | u16 *ch0_status_int = &(fpga ? fpga1 : fpga0)->ch0_status_int; | |
303 | for (k = 0; k < 32; ++k) { | |
304 | u16 status = in_le16(ch0_status_int + 4*k); | |
305 | if (!(status & (1 << 4))) { | |
306 | failed = 1; | |
307 | printf("fpga %d channel %d: no serdes lock\n", | |
308 | fpga, k); | |
309 | } | |
310 | /* reset events */ | |
311 | out_le16(ch0_status_int + 4*k, status); | |
312 | } | |
313 | } | |
314 | blank_string(strlen(str_locks)); | |
315 | ||
06b17412 DE |
316 | /* verify hicb_status */ |
317 | puts(str_hicb); | |
318 | for (fpga = 0; fpga < 2; ++fpga) { | |
319 | u16 *ch0_hicb_status_int = &(fpga ? fpga1 : fpga0)->ch0_hicb_status_int; | |
320 | for (k = 0; k < 32; ++k) { | |
321 | u16 status = in_le16(ch0_hicb_status_int + 4*k); | |
322 | if (status) | |
323 | printf("fpga %d hicb %d: hicb status %04x\n", | |
324 | fpga, k, status); | |
325 | /* reset events */ | |
326 | out_le16(ch0_hicb_status_int + 4*k, status); | |
327 | } | |
328 | } | |
329 | blank_string(strlen(str_hicb)); | |
330 | ||
255ef4d9 DE |
331 | /* verify phy status */ |
332 | puts(str_status); | |
333 | for (k = 0; k < 32; ++k) { | |
334 | if (verify_gbit_phy(CONFIG_SYS_GBIT_MII_BUSNAME, k)) { | |
335 | printf("verify baseboard phy %d failed\n", k); | |
336 | failed = 1; | |
337 | } | |
338 | putc('\b'); | |
339 | putc(slash[k % 8]); | |
340 | } | |
341 | for (k = 0; k < 32; ++k) { | |
342 | if (verify_gbit_phy(CONFIG_SYS_GBIT_MII1_BUSNAME, k)) { | |
343 | printf("verify extensionboard phy %d failed\n", k); | |
344 | failed = 1; | |
345 | } | |
346 | putc('\b'); | |
347 | putc(slash[k % 8]); | |
348 | } | |
349 | blank_string(strlen(str_status)); | |
350 | ||
351 | printf("Starting 64 channels %s\n", failed ? "failed" : "ok"); | |
352 | ||
353 | return 0; | |
354 | } | |
355 | ||
356 | void gd405ex_init(void) | |
357 | { | |
358 | unsigned int k; | |
359 | ||
360 | if (i2c_probe(0x22)) { /* i2c_probe returns 0 on success */ | |
361 | for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k) | |
923a662f | 362 | gd->arch.fpga_state[k] |= FPGA_STATE_PLATFORM; |
255ef4d9 DE |
363 | } else { |
364 | pca9698_direction_output(0x22, 39, 1); | |
365 | } | |
366 | } | |
367 | ||
368 | void gd405ex_set_fpga_reset(unsigned state) | |
369 | { | |
370 | int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM; | |
371 | ||
372 | if (legacy) { | |
373 | if (state) { | |
374 | out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET); | |
375 | out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET); | |
376 | } else { | |
377 | out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT); | |
378 | out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT); | |
379 | } | |
380 | } else { | |
381 | pca9698_set_value(0x22, 39, state ? 0 : 1); | |
382 | } | |
383 | } | |
384 | ||
385 | void gd405ex_setup_hw(void) | |
386 | { | |
387 | gpio_write_bit(CONFIG_SYS_GPIO_STARTUP_FINISHED_N, 0); | |
388 | gpio_write_bit(CONFIG_SYS_GPIO_STARTUP_FINISHED, 1); | |
389 | } | |
390 | ||
391 | int gd405ex_get_fpga_done(unsigned fpga) | |
392 | { | |
393 | int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM; | |
394 | ||
395 | if (legacy) | |
396 | return in_le16((void *)LATCH3_BASE) | |
397 | & CONFIG_SYS_FPGA_DONE(fpga); | |
398 | else | |
399 | return pca9698_get_value(0x22, fpga ? 9 : 8); | |
400 | } |