blob: fa8961a35177a78cd9de65b4596166a5554862bd [file] [log] [blame]
Dirk Eibach255ef4d2011-10-20 11:12:55 +02001/*
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 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
Dirk Eibach255ef4d2011-10-20 11:12:55 +02009 */
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
31DECLARE_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
45enum {
46 UNITTYPE_CCD_SWITCH = 1,
47};
48
49enum {
50 HWVER_100 = 0,
51 HWVER_110 = 1,
52};
53
54static 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 */
69int 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
85static void print_fpga_info(unsigned dev)
86{
Dirk Eibach0e60aa82012-04-27 10:33:46 +020087 struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(dev);
Dirk Eibach255ef4d2011-10-20 11:12:55 +020088 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
150int 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
164int 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
200err_out:
201 printf("Error writing to the PHY addr=%02x\n", addr);
202 return -1;
203}
204
205int 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
220err_out:
221 printf("Error writing to the PHY addr=%02x\n", addr);
222 return -1;
223}
224
225int last_stage_init(void)
226{
227 unsigned int k;
228 unsigned int fpga;
Dirk Eibach0e60aa82012-04-27 10:33:46 +0200229 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);
Dirk Eibach255ef4d2011-10-20 11:12:55 +0200231 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";
Dirk Eibach06b17412012-01-02 11:02:46 +0100236 char str_hicb[] = "Verify HICB status";
Dirk Eibach255ef4d2011-10-20 11:12:55 +0200237 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
Dirk Eibach06b17412012-01-02 11:02:46 +0100300 /* 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
Dirk Eibach255ef4d2011-10-20 11:12:55 +0200315 /* 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
340void 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)
Simon Glass923a6622012-12-13 20:49:02 +0000346 gd->arch.fpga_state[k] |= FPGA_STATE_PLATFORM;
Dirk Eibach255ef4d2011-10-20 11:12:55 +0200347 } else {
348 pca9698_direction_output(0x22, 39, 1);
349 }
350}
351
352void 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
369void 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
375int 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}