uboot/board/freescale/b4860qds/b4860qds.c
<<
>>
Prefs
   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
  47DECLARE_GLOBAL_DATA_PTR;
  48
  49int 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
 112int 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
 126int 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
 271int 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
 308unsigned 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
 323unsigned 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
 338static 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
 379static 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
 397int 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
 434void 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 */
 470void 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