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