uboot/arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Freescale Semiconductor, Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <asm/fsl_serdes.h>
   9#include <asm/immap_85xx.h>
  10#include <asm/io.h>
  11#include <asm/processor.h>
  12#include <asm/fsl_law.h>
  13#include <asm/errno.h>
  14#include <asm/fsl_errata.h>
  15#include "fsl_corenet2_serdes.h"
  16
  17#ifdef CONFIG_SYS_FSL_SRDS_1
  18static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
  19#endif
  20#ifdef CONFIG_SYS_FSL_SRDS_2
  21static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
  22#endif
  23#ifdef CONFIG_SYS_FSL_SRDS_3
  24static u8 serdes3_prtcl_map[SERDES_PRCTL_COUNT];
  25#endif
  26#ifdef CONFIG_SYS_FSL_SRDS_4
  27static u8 serdes4_prtcl_map[SERDES_PRCTL_COUNT];
  28#endif
  29
  30#ifdef DEBUG
  31static const char *serdes_prtcl_str[] = {
  32        [NONE] = "NA",
  33        [PCIE1] = "PCIE1",
  34        [PCIE2] = "PCIE2",
  35        [PCIE3] = "PCIE3",
  36        [PCIE4] = "PCIE4",
  37        [SATA1] = "SATA1",
  38        [SATA2] = "SATA2",
  39        [SRIO1] = "SRIO1",
  40        [SRIO2] = "SRIO2",
  41        [SGMII_FM1_DTSEC1] = "SGMII_FM1_DTSEC1",
  42        [SGMII_FM1_DTSEC2] = "SGMII_FM1_DTSEC2",
  43        [SGMII_FM1_DTSEC3] = "SGMII_FM1_DTSEC3",
  44        [SGMII_FM1_DTSEC4] = "SGMII_FM1_DTSEC4",
  45        [SGMII_FM1_DTSEC5] = "SGMII_FM1_DTSEC5",
  46        [SGMII_FM1_DTSEC6] = "SGMII_FM1_DTSEC6",
  47        [SGMII_FM2_DTSEC1] = "SGMII_FM2_DTSEC1",
  48        [SGMII_FM2_DTSEC2] = "SGMII_FM2_DTSEC2",
  49        [SGMII_FM2_DTSEC3] = "SGMII_FM2_DTSEC3",
  50        [SGMII_FM2_DTSEC4] = "SGMII_FM2_DTSEC4",
  51        [XAUI_FM1] = "XAUI_FM1",
  52        [XAUI_FM2] = "XAUI_FM2",
  53        [AURORA] = "DEBUG",
  54        [CPRI1] = "CPRI1",
  55        [CPRI2] = "CPRI2",
  56        [CPRI3] = "CPRI3",
  57        [CPRI4] = "CPRI4",
  58        [CPRI5] = "CPRI5",
  59        [CPRI6] = "CPRI6",
  60        [CPRI7] = "CPRI7",
  61        [CPRI8] = "CPRI8",
  62        [XAUI_FM1_MAC9] = "XAUI_FM1_MAC9",
  63        [XAUI_FM1_MAC10] = "XAUI_FM1_MAC10",
  64        [XAUI_FM2_MAC9] = "XAUI_FM2_MAC9",
  65        [XAUI_FM2_MAC10] = "XAUI_FM2_MAC10",
  66        [HIGIG_FM1_MAC9] = "HiGig_FM1_MAC9",
  67        [HIGIG_FM1_MAC10] = "HiGig_FM1_MAC10",
  68        [HIGIG_FM2_MAC9] = "HiGig_FM2_MAC9",
  69        [HIGIG_FM2_MAC10] = "HiGig_FM2_MAC10",
  70        [QSGMII_FM1_A] = "QSGMII_FM1_A",
  71        [QSGMII_FM1_B] = "QSGMII_FM1_B",
  72        [QSGMII_FM2_A] = "QSGMII_FM2_A",
  73        [QSGMII_FM2_B] = "QSGMII_FM2_B",
  74        [XFI_FM1_MAC9] = "XFI_FM1_MAC9",
  75        [XFI_FM1_MAC10] = "XFI_FM1_MAC10",
  76        [XFI_FM2_MAC9] = "XFI_FM2_MAC9",
  77        [XFI_FM2_MAC10] = "XFI_FM2_MAC10",
  78        [INTERLAKEN] = "INTERLAKEN",
  79        [QSGMII_SW1_A] = "QSGMII_SW1_A",
  80        [QSGMII_SW1_B] = "QSGMII_SW1_B",
  81        [SGMII_SW1_MAC1] = "SGMII_SW1_MAC1",
  82        [SGMII_SW1_MAC2] = "SGMII_SW1_MAC2",
  83        [SGMII_SW1_MAC3] = "SGMII_SW1_MAC3",
  84        [SGMII_SW1_MAC4] = "SGMII_SW1_MAC4",
  85        [SGMII_SW1_MAC5] = "SGMII_SW1_MAC5",
  86        [SGMII_SW1_MAC6] = "SGMII_SW1_MAC6",
  87};
  88#endif
  89
  90int is_serdes_configured(enum srds_prtcl device)
  91{
  92        int ret = 0;
  93
  94#ifdef CONFIG_SYS_FSL_SRDS_1
  95        ret |= serdes1_prtcl_map[device];
  96#endif
  97#ifdef CONFIG_SYS_FSL_SRDS_2
  98        ret |= serdes2_prtcl_map[device];
  99#endif
 100#ifdef CONFIG_SYS_FSL_SRDS_3
 101        ret |= serdes3_prtcl_map[device];
 102#endif
 103#ifdef CONFIG_SYS_FSL_SRDS_4
 104        ret |= serdes4_prtcl_map[device];
 105#endif
 106
 107        return !!ret;
 108}
 109
 110int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
 111{
 112        const ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 113        u32 cfg = in_be32(&gur->rcwsr[4]);
 114        int i;
 115
 116        switch (sd) {
 117#ifdef CONFIG_SYS_FSL_SRDS_1
 118        case FSL_SRDS_1:
 119                cfg &= FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
 120                cfg >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
 121                break;
 122#endif
 123#ifdef CONFIG_SYS_FSL_SRDS_2
 124        case FSL_SRDS_2:
 125                cfg &= FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
 126                cfg >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
 127                break;
 128#endif
 129#ifdef CONFIG_SYS_FSL_SRDS_3
 130        case FSL_SRDS_3:
 131                cfg &= FSL_CORENET2_RCWSR4_SRDS3_PRTCL;
 132                cfg >>= FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT;
 133                break;
 134#endif
 135#ifdef CONFIG_SYS_FSL_SRDS_4
 136        case FSL_SRDS_4:
 137                cfg &= FSL_CORENET2_RCWSR4_SRDS4_PRTCL;
 138                cfg >>= FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT;
 139                break;
 140#endif
 141        default:
 142                printf("invalid SerDes%d\n", sd);
 143                break;
 144        }
 145        /* Is serdes enabled at all? */
 146        if (unlikely(cfg == 0))
 147                return -ENODEV;
 148
 149        for (i = 0; i < SRDS_MAX_LANES; i++) {
 150                if (serdes_get_prtcl(sd, cfg, i) == device)
 151                        return i;
 152        }
 153
 154        return -ENODEV;
 155}
 156
 157#define BC3_SHIFT       9
 158#define DC3_SHIFT       6
 159#define FC3_SHIFT       0
 160#define BC2_SHIFT       19
 161#define DC2_SHIFT       16
 162#define FC2_SHIFT       10
 163#define BC1_SHIFT       29
 164#define DC1_SHIFT       26
 165#define FC1_SHIFT       20
 166#define BC_MASK         0x1
 167#define DC_MASK         0x7
 168#define FC_MASK         0x3F
 169
 170#define FUSE_VAL_MASK           0x00000003
 171#define FUSE_VAL_SHIFT          30
 172#define CR0_DCBIAS_SHIFT        5
 173#define CR1_FCAP_SHIFT          15
 174#define CR1_BCAP_SHIFT          29
 175#define FCAP_MASK               0x001F8000
 176#define BCAP_MASK               0x20000000
 177#define BCAP_OVD_MASK           0x10000000
 178#define BYP_CAL_MASK            0x02000000
 179
 180void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
 181                u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
 182{
 183        ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 184        u32 cfg;
 185        int lane;
 186
 187        memset(serdes_prtcl_map, 0, sizeof(serdes_prtcl_map));
 188#ifdef CONFIG_SYS_FSL_ERRATUM_A007186
 189        struct ccsr_sfp_regs  __iomem *sfp_regs =
 190                        (struct ccsr_sfp_regs __iomem *)(CONFIG_SYS_SFP_ADDR);
 191        u32 pll_num, pll_status, bc, dc, fc, pll_cr_upd, pll_cr0, pll_cr1;
 192        u32 bc_status, fc_status, dc_status, pll_sr2;
 193        serdes_corenet_t  __iomem *srds_regs = (void *)sd_addr;
 194        u32 sfp_spfr0, sel;
 195#endif
 196
 197        cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask;
 198
 199/* Erratum A-007186
 200 * Freescale Scratch Pad Fuse Register n (SFP_FSPFR0)
 201 * The workaround requires factory pre-set SerDes calibration values to be
 202 * read from a fuse block(Freescale Scratch Pad Fuse Register SFP_FSPFR0)
 203 * These values have been shown to work across the
 204 * entire temperature range for all SerDes. These values are then written into
 205 * the SerDes registers to calibrate the SerDes PLL.
 206 *
 207 * This workaround for the protocols and rates that only have the Ring VCO.
 208 */
 209#ifdef CONFIG_SYS_FSL_ERRATUM_A007186
 210        sfp_spfr0 = in_be32(&sfp_regs->fsl_spfr0);
 211        debug("A007186: sfp_spfr0= %x\n", sfp_spfr0);
 212
 213        sel = (sfp_spfr0 >> FUSE_VAL_SHIFT) & FUSE_VAL_MASK;
 214
 215        if (has_erratum_a007186() && (sel == 0x01 || sel == 0x02)) {
 216                for (pll_num = 0; pll_num < SRDS_MAX_BANK; pll_num++) {
 217                        pll_status = in_be32(&srds_regs->bank[pll_num].pllcr0);
 218                        debug("A007186: pll_num=%x pllcr0=%x\n",
 219                              pll_num, pll_status);
 220                        /* STEP 1 */
 221                        /* Read factory pre-set SerDes calibration values
 222                         * from fuse block(SFP scratch register-sfp_spfr0)
 223                         */
 224                        switch (pll_status & SRDS_PLLCR0_FRATE_SEL_MASK) {
 225                        case SRDS_PLLCR0_FRATE_SEL_3_0:
 226                        case SRDS_PLLCR0_FRATE_SEL_3_072:
 227                                debug("A007186: 3.0/3.072 protocol rate\n");
 228                                bc = (sfp_spfr0 >> BC1_SHIFT) & BC_MASK;
 229                                dc = (sfp_spfr0 >> DC1_SHIFT) & DC_MASK;
 230                                fc = (sfp_spfr0 >> FC1_SHIFT) & FC_MASK;
 231                                break;
 232                        case SRDS_PLLCR0_FRATE_SEL_3_125:
 233                                debug("A007186: 3.125 protocol rate\n");
 234                                bc = (sfp_spfr0 >> BC2_SHIFT) & BC_MASK;
 235                                dc = (sfp_spfr0 >> DC2_SHIFT) & DC_MASK;
 236                                fc = (sfp_spfr0 >> FC2_SHIFT) & FC_MASK;
 237                                break;
 238                        case SRDS_PLLCR0_FRATE_SEL_3_75:
 239                                debug("A007186: 3.75 protocol rate\n");
 240                                bc = (sfp_spfr0 >> BC1_SHIFT) & BC_MASK;
 241                                dc = (sfp_spfr0 >> DC1_SHIFT) & DC_MASK;
 242                                fc = (sfp_spfr0 >> FC1_SHIFT) & FC_MASK;
 243                                break;
 244                        default:
 245                                continue;
 246                        }
 247
 248                        /* STEP 2 */
 249                        /* Write SRDSxPLLnCR1[11:16] = FC
 250                         * Write SRDSxPLLnCR1[2] = BC
 251                         */
 252                        pll_cr1 = in_be32(&srds_regs->bank[pll_num].pllcr1);
 253                        pll_cr_upd = (((bc << CR1_BCAP_SHIFT) & BCAP_MASK) |
 254                                      ((fc << CR1_FCAP_SHIFT) & FCAP_MASK));
 255                        out_be32(&srds_regs->bank[pll_num].pllcr1,
 256                                 (pll_cr_upd | pll_cr1));
 257                        debug("A007186: pll_num=%x Updated PLLCR1=%x\n",
 258                              pll_num, (pll_cr_upd | pll_cr1));
 259                        /* Write SRDSxPLLnCR0[24:26] = DC
 260                         */
 261                        pll_cr0 = in_be32(&srds_regs->bank[pll_num].pllcr0);
 262                        out_be32(&srds_regs->bank[pll_num].pllcr0,
 263                                 pll_cr0 | (dc << CR0_DCBIAS_SHIFT));
 264                        debug("A007186: pll_num=%x, Updated PLLCR0=%x\n",
 265                              pll_num, (pll_cr0 | (dc << CR0_DCBIAS_SHIFT)));
 266                        /* Write SRDSxPLLnCR1[3] = 1
 267                         * Write SRDSxPLLnCR1[6] = 1
 268                         */
 269                        pll_cr1 = in_be32(&srds_regs->bank[pll_num].pllcr1);
 270                        pll_cr_upd = (BCAP_OVD_MASK | BYP_CAL_MASK);
 271                        out_be32(&srds_regs->bank[pll_num].pllcr1,
 272                                 (pll_cr_upd | pll_cr1));
 273                        debug("A007186: pll_num=%x Updated PLLCR1=%x\n",
 274                              pll_num, (pll_cr_upd | pll_cr1));
 275
 276                        /* STEP 3 */
 277                        /* Read the status Registers */
 278                        /* Verify SRDSxPLLnSR2[8] = BC */
 279                        pll_sr2 = in_be32(&srds_regs->bank[pll_num].pllsr2);
 280                        debug("A007186: pll_num=%x pllsr2=%x\n",
 281                              pll_num, pll_sr2);
 282                        bc_status = (pll_sr2 >> 23) & BC_MASK;
 283                        if (bc_status != bc)
 284                                debug("BC mismatch\n");
 285                        fc_status = (pll_sr2 >> 16) & FC_MASK;
 286                        if (fc_status != fc)
 287                                debug("FC mismatch\n");
 288                        pll_cr0 = in_be32(&srds_regs->bank[pll_num].pllcr0);
 289                        out_be32(&srds_regs->bank[pll_num].pllcr0, pll_cr0 |
 290                                                                0x02000000);
 291                        pll_sr2 = in_be32(&srds_regs->bank[pll_num].pllsr2);
 292                        dc_status = (pll_sr2 >> 17) & DC_MASK;
 293                        if (dc_status != dc)
 294                                debug("DC mismatch\n");
 295                        pll_cr0 = in_be32(&srds_regs->bank[pll_num].pllcr0);
 296                        out_be32(&srds_regs->bank[pll_num].pllcr0, pll_cr0 &
 297                                                                0xfdffffff);
 298
 299                        /* STEP 4 */
 300                        /* Wait 750us to verify the PLL is locked
 301                         * by checking SRDSxPLLnCR0[8] = 1.
 302                         */
 303                        udelay(750);
 304                        pll_status = in_be32(&srds_regs->bank[pll_num].pllcr0);
 305                        debug("A007186: pll_num=%x pllcr0=%x\n",
 306                              pll_num, pll_status);
 307
 308                        if ((pll_status & SRDS_PLLCR0_PLL_LCK) == 0)
 309                                printf("A007186 Serdes PLL not locked\n");
 310                        else
 311                                debug("A007186 Serdes PLL locked\n");
 312                }
 313        }
 314#endif
 315
 316        cfg >>= sd_prctl_shift;
 317        printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
 318        if (!is_serdes_prtcl_valid(sd, cfg))
 319                printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
 320
 321        for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
 322                enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
 323                if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
 324                        debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
 325                else
 326                        serdes_prtcl_map[lane_prtcl] = 1;
 327        }
 328}
 329
 330void fsl_serdes_init(void)
 331{
 332
 333#ifdef CONFIG_SYS_FSL_SRDS_1
 334        serdes_init(FSL_SRDS_1,
 335                    CONFIG_SYS_FSL_CORENET_SERDES_ADDR,
 336                    FSL_CORENET2_RCWSR4_SRDS1_PRTCL,
 337                    FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT,
 338                    serdes1_prtcl_map);
 339#endif
 340#ifdef CONFIG_SYS_FSL_SRDS_2
 341        serdes_init(FSL_SRDS_2,
 342                    CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_2 * 0x1000,
 343                    FSL_CORENET2_RCWSR4_SRDS2_PRTCL,
 344                    FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT,
 345                    serdes2_prtcl_map);
 346#endif
 347#ifdef CONFIG_SYS_FSL_SRDS_3
 348        serdes_init(FSL_SRDS_3,
 349                    CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_3 * 0x1000,
 350                    FSL_CORENET2_RCWSR4_SRDS3_PRTCL,
 351                    FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT,
 352                    serdes3_prtcl_map);
 353#endif
 354#ifdef CONFIG_SYS_FSL_SRDS_4
 355        serdes_init(FSL_SRDS_4,
 356                    CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_4 * 0x1000,
 357                    FSL_CORENET2_RCWSR4_SRDS4_PRTCL,
 358                    FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT,
 359                    serdes4_prtcl_map);
 360#endif
 361
 362}
 363
 364const char *serdes_clock_to_string(u32 clock)
 365{
 366        switch (clock) {
 367        case SRDS_PLLCR0_RFCK_SEL_100:
 368                return "100";
 369        case SRDS_PLLCR0_RFCK_SEL_125:
 370                return "125";
 371        case SRDS_PLLCR0_RFCK_SEL_156_25:
 372                return "156.25";
 373        case SRDS_PLLCR0_RFCK_SEL_161_13:
 374                return "161.1328123";
 375        default:
 376#if defined(CONFIG_T4240QDS)
 377                return "???";
 378#else
 379                return "122.88";
 380#endif
 381        }
 382}
 383
 384