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