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