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