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