xref: /openbmc/u-boot/board/freescale/b4860qds/b4860qds.c (revision f165bc35285460f9739a234de379a535519f39e6)
1 /*
2  * Copyright 2011-2012 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <command.h>
9 #include <i2c.h>
10 #include <netdev.h>
11 #include <linux/compiler.h>
12 #include <asm/mmu.h>
13 #include <asm/processor.h>
14 #include <asm/cache.h>
15 #include <asm/immap_85xx.h>
16 #include <asm/fsl_law.h>
17 #include <asm/fsl_serdes.h>
18 #include <asm/fsl_portals.h>
19 #include <asm/fsl_liodn.h>
20 #include <fm_eth.h>
21 
22 #include "../common/qixis.h"
23 #include "../common/vsc3316_3308.h"
24 #include "b4860qds.h"
25 #include "b4860qds_qixis.h"
26 #include "b4860qds_crossbar_con.h"
27 
28 #define CLK_MUX_SEL_MASK	0x4
29 #define ETH_PHY_CLK_OUT		0x4
30 
31 DECLARE_GLOBAL_DATA_PTR;
32 
33 int checkboard(void)
34 {
35 	char buf[64];
36 	u8 sw;
37 	struct cpu_type *cpu = gd->arch.cpu;
38 	static const char *const freq[] = {"100", "125", "156.25", "161.13",
39 						"122.88", "122.88", "122.88"};
40 	int clock;
41 
42 	printf("Board: %sQDS, ", cpu->name);
43 	printf("Sys ID: 0x%02x, Sys Ver: 0x%02x, ",
44 		QIXIS_READ(id), QIXIS_READ(arch));
45 
46 	sw = QIXIS_READ(brdcfg[0]);
47 	sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
48 
49 	if (sw < 0x8)
50 		printf("vBank: %d\n", sw);
51 	else if (sw >= 0x8 && sw <= 0xE)
52 		puts("NAND\n");
53 	else
54 		printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
55 
56 	printf("FPGA: v%d (%s), build %d",
57 		(int)QIXIS_READ(scver), qixis_read_tag(buf),
58 		(int)qixis_read_minor());
59 	/* the timestamp string contains "\n" at the end */
60 	printf(" on %s", qixis_read_time(buf));
61 
62 	/*
63 	 * Display the actual SERDES reference clocks as configured by the
64 	 * dip switches on the board.  Note that the SWx registers could
65 	 * technically be set to force the reference clocks to match the
66 	 * values that the SERDES expects (or vice versa).  For now, however,
67 	 * we just display both values and hope the user notices when they
68 	 * don't match.
69 	 */
70 	puts("SERDES Reference Clocks: ");
71 	sw = QIXIS_READ(brdcfg[2]);
72 	clock = (sw >> 5) & 7;
73 	printf("Bank1=%sMHz ", freq[clock]);
74 	sw = QIXIS_READ(brdcfg[4]);
75 	clock = (sw >> 6) & 3;
76 	printf("Bank2=%sMHz\n", freq[clock]);
77 
78 	return 0;
79 }
80 
81 int select_i2c_ch_pca(u8 ch)
82 {
83 	int ret;
84 
85 	/* Selecting proper channel via PCA*/
86 	ret = i2c_write(I2C_MUX_PCA_ADDR, 0x0, 1, &ch, 1);
87 	if (ret) {
88 		printf("PCA: failed to select proper channel.\n");
89 		return ret;
90 	}
91 
92 	return 0;
93 }
94 
95 int configure_vsc3316_3308(void)
96 {
97 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
98 	unsigned int num_vsc16_con, num_vsc08_con;
99 	u32 serdes1_prtcl, serdes2_prtcl;
100 	int ret;
101 
102 	serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
103 			FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
104 	if (!serdes1_prtcl) {
105 		printf("SERDES1 is not enabled\n");
106 		return 0;
107 	}
108 	serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
109 	debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
110 
111 	serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
112 			FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
113 	if (!serdes2_prtcl) {
114 		printf("SERDES2 is not enabled\n");
115 		return 0;
116 	}
117 	serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
118 	debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
119 
120 	switch (serdes1_prtcl) {
121 	case 0x2a:
122 	case 0x2C:
123 	case 0x2D:
124 	case 0x2E:
125 			/*
126 			 * Configuration:
127 			 * SERDES: 1
128 			 * Lanes: A,B: SGMII
129 			 * Lanes: C,D,E,F,G,H: CPRI
130 			 */
131 		debug("Configuring crossbar to use onboard SGMII PHYs:"
132 				"srds_prctl:%x\n", serdes1_prtcl);
133 		num_vsc16_con = NUM_CON_VSC3316;
134 		/* Configure VSC3316 crossbar switch */
135 		ret = select_i2c_ch_pca(I2C_CH_VSC3316);
136 		if (!ret) {
137 			ret = vsc3316_config(VSC3316_TX_ADDRESS,
138 					vsc16_tx_4sfp_sgmii_12_56,
139 					num_vsc16_con);
140 			if (ret)
141 				return ret;
142 			ret = vsc3316_config(VSC3316_RX_ADDRESS,
143 					vsc16_rx_4sfp_sgmii_12_56,
144 					num_vsc16_con);
145 			if (ret)
146 				return ret;
147 		} else {
148 			return ret;
149 		}
150 		break;
151 
152 #ifdef CONFIG_PPC_B4420
153 	case 0x18:
154 			/*
155 			 * Configuration:
156 			 * SERDES: 1
157 			 * Lanes: A,B,C,D: SGMII
158 			 * Lanes: E,F,G,H: CPRI
159 			 */
160 		debug("Configuring crossbar to use onboard SGMII PHYs:"
161 				"srds_prctl:%x\n", serdes1_prtcl);
162 		num_vsc16_con = NUM_CON_VSC3316;
163 		/* Configure VSC3316 crossbar switch */
164 		ret = select_i2c_ch_pca(I2C_CH_VSC3316);
165 		if (!ret) {
166 			ret = vsc3316_config(VSC3316_TX_ADDRESS,
167 					vsc16_tx_sgmii_lane_cd, num_vsc16_con);
168 			if (ret)
169 				return ret;
170 			ret = vsc3316_config(VSC3316_RX_ADDRESS,
171 					vsc16_rx_sgmii_lane_cd, num_vsc16_con);
172 			if (ret)
173 				return ret;
174 		} else {
175 			return ret;
176 		}
177 		break;
178 #endif
179 
180 	case 0x3E:
181 	case 0x0D:
182 	case 0x0E:
183 	case 0x12:
184 		num_vsc16_con = NUM_CON_VSC3316;
185 		/* Configure VSC3316 crossbar switch */
186 		ret = select_i2c_ch_pca(I2C_CH_VSC3316);
187 		if (!ret) {
188 			ret = vsc3316_config(VSC3316_TX_ADDRESS,
189 					vsc16_tx_sfp, num_vsc16_con);
190 			if (ret)
191 				return ret;
192 			ret = vsc3316_config(VSC3316_RX_ADDRESS,
193 					vsc16_rx_sfp, num_vsc16_con);
194 			if (ret)
195 				return ret;
196 		} else {
197 			return ret;
198 		}
199 		break;
200 	default:
201 		printf("WARNING:VSC crossbars programming not supported for:%x"
202 					" SerDes1 Protocol.\n", serdes1_prtcl);
203 		return -1;
204 	}
205 
206 	switch (serdes2_prtcl) {
207 	case 0x9E:
208 	case 0x9A:
209 	case 0x98:
210 	case 0xb2:
211 	case 0x49:
212 	case 0x4E:
213 	case 0x8D:
214 	case 0x7A:
215 		num_vsc08_con = NUM_CON_VSC3308;
216 		/* Configure VSC3308 crossbar switch */
217 		ret = select_i2c_ch_pca(I2C_CH_VSC3308);
218 		if (!ret) {
219 			ret = vsc3308_config(VSC3308_TX_ADDRESS,
220 					vsc08_tx_amc, num_vsc08_con);
221 			if (ret)
222 				return ret;
223 			ret = vsc3308_config(VSC3308_RX_ADDRESS,
224 					vsc08_rx_amc, num_vsc08_con);
225 			if (ret)
226 				return ret;
227 		} else {
228 			return ret;
229 		}
230 		break;
231 	default:
232 		printf("WARNING:VSC crossbars programming not supported for: %x"
233 					" SerDes2 Protocol.\n", serdes2_prtcl);
234 		return -1;
235 	}
236 
237 	return 0;
238 }
239 
240 int board_early_init_r(void)
241 {
242 	const unsigned int flashbase = CONFIG_SYS_FLASH_BASE;
243 	const u8 flash_esel = find_tlb_idx((void *)flashbase, 1);
244 
245 	/*
246 	 * Remap Boot flash + PROMJET region to caching-inhibited
247 	 * so that flash can be erased properly.
248 	 */
249 
250 	/* Flush d-cache and invalidate i-cache of any FLASH data */
251 	flush_dcache();
252 	invalidate_icache();
253 
254 	/* invalidate existing TLB entry for flash + promjet */
255 	disable_tlb(flash_esel);
256 
257 	set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS,
258 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
259 			0, flash_esel, BOOKE_PAGESZ_256M, 1);
260 
261 	set_liodns();
262 #ifdef CONFIG_SYS_DPAA_QBMAN
263 	setup_portals();
264 #endif
265 
266 	/* Configure VSC3316 and VSC3308 crossbar switches */
267 	if (configure_vsc3316_3308())
268 		printf("VSC:failed to configure VSC3316/3308.\n");
269 	else
270 		printf("VSC:VSC3316/3308 successfully configured.\n");
271 
272 	select_i2c_ch_pca(I2C_CH_DEFAULT);
273 
274 	return 0;
275 }
276 
277 unsigned long get_board_sys_clk(void)
278 {
279 	u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
280 
281 	switch ((sysclk_conf & 0x0C) >> 2) {
282 	case QIXIS_CLK_100:
283 		return 100000000;
284 	case QIXIS_CLK_125:
285 		return 125000000;
286 	case QIXIS_CLK_133:
287 		return 133333333;
288 	}
289 	return 66666666;
290 }
291 
292 unsigned long get_board_ddr_clk(void)
293 {
294 	u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
295 
296 	switch (ddrclk_conf & 0x03) {
297 	case QIXIS_CLK_100:
298 		return 100000000;
299 	case QIXIS_CLK_125:
300 		return 125000000;
301 	case QIXIS_CLK_133:
302 		return 133333333;
303 	}
304 	return 66666666;
305 }
306 
307 static int serdes_refclock(u8 sw, u8 sdclk)
308 {
309 	unsigned int clock;
310 	int ret = -1;
311 	u8 brdcfg4;
312 
313 	if (sdclk == 1) {
314 		brdcfg4 = QIXIS_READ(brdcfg[4]);
315 		if ((brdcfg4 & CLK_MUX_SEL_MASK) == ETH_PHY_CLK_OUT)
316 			return SRDS_PLLCR0_RFCK_SEL_125;
317 		else
318 			clock = (sw >> 5) & 7;
319 	} else
320 		clock = (sw >> 6) & 3;
321 
322 	switch (clock) {
323 	case 0:
324 		ret = SRDS_PLLCR0_RFCK_SEL_100;
325 		break;
326 	case 1:
327 		ret = SRDS_PLLCR0_RFCK_SEL_125;
328 		break;
329 	case 2:
330 		ret = SRDS_PLLCR0_RFCK_SEL_156_25;
331 		break;
332 	case 3:
333 		ret = SRDS_PLLCR0_RFCK_SEL_161_13;
334 		break;
335 	case 4:
336 	case 5:
337 	case 6:
338 		ret = SRDS_PLLCR0_RFCK_SEL_122_88;
339 		break;
340 	default:
341 		ret = -1;
342 		break;
343 	}
344 
345 	return ret;
346 }
347 
348 static const char *serdes_clock_to_string(u32 clock)
349 {
350 	switch (clock) {
351 	case SRDS_PLLCR0_RFCK_SEL_100:
352 		return "100";
353 	case SRDS_PLLCR0_RFCK_SEL_125:
354 		return "125";
355 	case SRDS_PLLCR0_RFCK_SEL_156_25:
356 		return "156.25";
357 	case SRDS_PLLCR0_RFCK_SEL_161_13:
358 		return "161.13";
359 	default:
360 		return "122.88";
361 	}
362 }
363 
364 #define NUM_SRDS_BANKS	2
365 
366 int misc_init_r(void)
367 {
368 	u8 sw;
369 	serdes_corenet_t *srds_regs =
370 		(void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
371 	u32 actual[NUM_SRDS_BANKS];
372 	unsigned int i;
373 	int clock;
374 
375 	sw = QIXIS_READ(brdcfg[2]);
376 	clock = serdes_refclock(sw, 1);
377 	if (clock >= 0)
378 		actual[0] = clock;
379 	else
380 		printf("Warning: SDREFCLK1 switch setting is unsupported\n");
381 
382 	sw = QIXIS_READ(brdcfg[4]);
383 	clock = serdes_refclock(sw, 2);
384 	if (clock >= 0)
385 		actual[1] = clock;
386 	else
387 		printf("Warning: SDREFCLK2 switch setting unsupported\n");
388 
389 	for (i = 0; i < NUM_SRDS_BANKS; i++) {
390 		u32 pllcr0 = srds_regs->bank[i].pllcr0;
391 		u32 expected = pllcr0 & SRDS_PLLCR0_RFCK_SEL_MASK;
392 		if (expected != actual[i]) {
393 			printf("Warning: SERDES bank %u expects reference clock"
394 			       " %sMHz, but actual is %sMHz\n", i + 1,
395 			       serdes_clock_to_string(expected),
396 			       serdes_clock_to_string(actual[i]));
397 		}
398 	}
399 
400 	return 0;
401 }
402 
403 void ft_board_setup(void *blob, bd_t *bd)
404 {
405 	phys_addr_t base;
406 	phys_size_t size;
407 
408 	ft_cpu_setup(blob, bd);
409 
410 	base = getenv_bootm_low();
411 	size = getenv_bootm_size();
412 
413 	fdt_fixup_memory(blob, (u64)base, (u64)size);
414 
415 #ifdef CONFIG_PCI
416 	pci_of_setup(blob, bd);
417 #endif
418 
419 	fdt_fixup_liodn(blob);
420 
421 #ifdef CONFIG_HAS_FSL_DR_USB
422 	fdt_fixup_dr_usb(blob, bd);
423 #endif
424 
425 #ifdef CONFIG_SYS_DPAA_FMAN
426 	fdt_fixup_fman_ethernet(blob);
427 	fdt_fixup_board_enet(blob);
428 #endif
429 }
430 
431 /*
432  * Dump board switch settings.
433  * The bits that cannot be read/sampled via some FPGA or some
434  * registers, they will be displayed as
435  * underscore in binary format. mask[] has those bits.
436  * Some bits are calculated differently than the actual switches
437  * if booting with overriding by FPGA.
438  */
439 void qixis_dump_switch(void)
440 {
441 	int i;
442 	u8 sw[5];
443 
444 	/*
445 	 * Any bit with 1 means that bit cannot be reverse engineered.
446 	 * It will be displayed as _ in binary format.
447 	 */
448 	static const u8 mask[] = {0x07, 0, 0, 0xff, 0};
449 	char buf[10];
450 	u8 brdcfg[16], dutcfg[16];
451 
452 	for (i = 0; i < 16; i++) {
453 		brdcfg[i] = qixis_read(offsetof(struct qixis, brdcfg[0]) + i);
454 		dutcfg[i] = qixis_read(offsetof(struct qixis, dutcfg[0]) + i);
455 	}
456 
457 	sw[0] = ((brdcfg[0] & 0x0f) << 4)	| \
458 		(brdcfg[9] & 0x08);
459 	sw[1] = ((dutcfg[1] & 0x01) << 7)	| \
460 		((dutcfg[2] & 0x07) << 4)       | \
461 		((dutcfg[6] & 0x10) >> 1)       | \
462 		((dutcfg[6] & 0x80) >> 5)       | \
463 		((dutcfg[1] & 0x40) >> 5)       | \
464 		(dutcfg[6] & 0x01);
465 	sw[2] = dutcfg[0];
466 	sw[3] = 0;
467 	sw[4] = ((brdcfg[1] & 0x30) << 2)	| \
468 		((brdcfg[1] & 0xc0) >> 2)	| \
469 		(brdcfg[1] & 0x0f);
470 
471 	puts("DIP switch settings:\n");
472 	for (i = 0; i < 5; i++) {
473 		printf("SW%d         = 0b%s (0x%02x)\n",
474 			i + 1, byte_to_binary_mask(sw[i], mask[i], buf), sw[i]);
475 	}
476 }
477