2 * Copyright 2011-2012 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0+
11 #include <linux/compiler.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>
22 #include "../common/qixis.h"
23 #include "../common/vsc3316_3308.h"
25 #include "b4860qds_qixis.h"
26 #include "b4860qds_crossbar_con.h"
28 #define CLK_MUX_SEL_MASK 0x4
29 #define ETH_PHY_CLK_OUT 0x4
31 DECLARE_GLOBAL_DATA_PTR;
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"};
42 printf("Board: %sQDS, ", cpu->name);
43 printf("Sys ID: 0x%02x, Sys Ver: 0x%02x, ",
44 QIXIS_READ(id), QIXIS_READ(arch));
46 sw = QIXIS_READ(brdcfg[0]);
47 sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
50 printf("vBank: %d\n", sw);
51 else if (sw >= 0x8 && sw <= 0xE)
54 printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
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));
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
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]);
81 int select_i2c_ch_pca(u8 ch)
85 /* Selecting proper channel via PCA*/
86 ret = i2c_write(I2C_MUX_PCA_ADDR, 0x0, 1, &ch, 1);
88 printf("PCA: failed to select proper channel.\n");
95 int configure_vsc3316_3308(void)
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;
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");
108 serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
109 debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
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");
117 serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
118 debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
120 switch (serdes1_prtcl) {
129 * Lanes: C,D,E,F,G,H: CPRI
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);
137 ret = vsc3316_config(VSC3316_TX_ADDRESS,
138 vsc16_tx_4sfp_sgmii_12_56,
142 ret = vsc3316_config(VSC3316_RX_ADDRESS,
143 vsc16_rx_4sfp_sgmii_12_56,
152 #ifdef CONFIG_PPC_B4420
157 * Lanes: A,B,C,D: SGMII
158 * Lanes: E,F,G,H: CPRI
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);
166 ret = vsc3316_config(VSC3316_TX_ADDRESS,
167 vsc16_tx_sgmii_lane_cd, num_vsc16_con);
170 ret = vsc3316_config(VSC3316_RX_ADDRESS,
171 vsc16_rx_sgmii_lane_cd, num_vsc16_con);
184 num_vsc16_con = NUM_CON_VSC3316;
185 /* Configure VSC3316 crossbar switch */
186 ret = select_i2c_ch_pca(I2C_CH_VSC3316);
188 ret = vsc3316_config(VSC3316_TX_ADDRESS,
189 vsc16_tx_sfp, num_vsc16_con);
192 ret = vsc3316_config(VSC3316_RX_ADDRESS,
193 vsc16_rx_sfp, num_vsc16_con);
201 printf("WARNING:VSC crossbars programming not supported for:%x"
202 " SerDes1 Protocol.\n", serdes1_prtcl);
206 switch (serdes2_prtcl) {
215 num_vsc08_con = NUM_CON_VSC3308;
216 /* Configure VSC3308 crossbar switch */
217 ret = select_i2c_ch_pca(I2C_CH_VSC3308);
219 ret = vsc3308_config(VSC3308_TX_ADDRESS,
220 vsc08_tx_amc, num_vsc08_con);
223 ret = vsc3308_config(VSC3308_RX_ADDRESS,
224 vsc08_rx_amc, num_vsc08_con);
232 printf("WARNING:VSC crossbars programming not supported for: %x"
233 " SerDes2 Protocol.\n", serdes2_prtcl);
240 int board_early_init_r(void)
242 const unsigned int flashbase = CONFIG_SYS_FLASH_BASE;
243 const u8 flash_esel = find_tlb_idx((void *)flashbase, 1);
246 * Remap Boot flash + PROMJET region to caching-inhibited
247 * so that flash can be erased properly.
250 /* Flush d-cache and invalidate i-cache of any FLASH data */
254 /* invalidate existing TLB entry for flash + promjet */
255 disable_tlb(flash_esel);
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);
262 #ifdef CONFIG_SYS_DPAA_QBMAN
266 /* Configure VSC3316 and VSC3308 crossbar switches */
267 if (configure_vsc3316_3308())
268 printf("VSC:failed to configure VSC3316/3308.\n");
270 printf("VSC:VSC3316/3308 successfully configured.\n");
272 select_i2c_ch_pca(I2C_CH_DEFAULT);
277 unsigned long get_board_sys_clk(void)
279 u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
281 switch ((sysclk_conf & 0x0C) >> 2) {
292 unsigned long get_board_ddr_clk(void)
294 u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
296 switch (ddrclk_conf & 0x03) {
307 static int serdes_refclock(u8 sw, u8 sdclk)
314 brdcfg4 = QIXIS_READ(brdcfg[4]);
315 if ((brdcfg4 & CLK_MUX_SEL_MASK) == ETH_PHY_CLK_OUT)
316 return SRDS_PLLCR0_RFCK_SEL_125;
318 clock = (sw >> 5) & 7;
320 clock = (sw >> 6) & 3;
324 ret = SRDS_PLLCR0_RFCK_SEL_100;
327 ret = SRDS_PLLCR0_RFCK_SEL_125;
330 ret = SRDS_PLLCR0_RFCK_SEL_156_25;
333 ret = SRDS_PLLCR0_RFCK_SEL_161_13;
338 ret = SRDS_PLLCR0_RFCK_SEL_122_88;
348 static const char *serdes_clock_to_string(u32 clock)
351 case SRDS_PLLCR0_RFCK_SEL_100:
353 case SRDS_PLLCR0_RFCK_SEL_125:
355 case SRDS_PLLCR0_RFCK_SEL_156_25:
357 case SRDS_PLLCR0_RFCK_SEL_161_13:
364 #define NUM_SRDS_BANKS 2
366 int misc_init_r(void)
369 serdes_corenet_t *srds_regs =
370 (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
371 u32 actual[NUM_SRDS_BANKS];
375 sw = QIXIS_READ(brdcfg[2]);
376 clock = serdes_refclock(sw, 1);
380 printf("Warning: SDREFCLK1 switch setting is unsupported\n");
382 sw = QIXIS_READ(brdcfg[4]);
383 clock = serdes_refclock(sw, 2);
387 printf("Warning: SDREFCLK2 switch setting unsupported\n");
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]));
403 void ft_board_setup(void *blob, bd_t *bd)
408 ft_cpu_setup(blob, bd);
410 base = getenv_bootm_low();
411 size = getenv_bootm_size();
413 fdt_fixup_memory(blob, (u64)base, (u64)size);
416 pci_of_setup(blob, bd);
419 fdt_fixup_liodn(blob);
421 #ifdef CONFIG_HAS_FSL_DR_USB
422 fdt_fixup_dr_usb(blob, bd);
425 #ifdef CONFIG_SYS_DPAA_FMAN
426 fdt_fixup_fman_ethernet(blob);
427 fdt_fixup_board_enet(blob);
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.
439 void qixis_dump_switch(void)
445 * Any bit with 1 means that bit cannot be reverse engineered.
446 * It will be displayed as _ in binary format.
448 static const u8 mask[] = {0x07, 0, 0, 0xff, 0};
450 u8 brdcfg[16], dutcfg[16];
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);
457 sw[0] = ((brdcfg[0] & 0x0f) << 4) | \
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) | \
467 sw[4] = ((brdcfg[1] & 0x30) << 2) | \
468 ((brdcfg[1] & 0xc0) >> 2) | \
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]);