uboot/arch/mips/mach-octeon/cvmx-helper-sgmii.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2018-2022 Marvell International Ltd.
   4 *
   5 * Functions for SGMII initialization, configuration,
   6 * and monitoring.
   7 */
   8
   9#include <time.h>
  10#include <log.h>
  11#include <linux/delay.h>
  12
  13#include <mach/cvmx-regs.h>
  14#include <mach/cvmx-csr.h>
  15#include <mach/cvmx-bootmem.h>
  16#include <mach/octeon-model.h>
  17#include <mach/cvmx-fuse.h>
  18#include <mach/octeon-feature.h>
  19#include <mach/cvmx-qlm.h>
  20#include <mach/octeon_qlm.h>
  21#include <mach/cvmx-pcie.h>
  22#include <mach/cvmx-coremask.h>
  23
  24#include <mach/cvmx-agl-defs.h>
  25#include <mach/cvmx-bgxx-defs.h>
  26#include <mach/cvmx-ciu-defs.h>
  27#include <mach/cvmx-gmxx-defs.h>
  28#include <mach/cvmx-ipd-defs.h>
  29#include <mach/cvmx-pcsx-defs.h>
  30#include <mach/cvmx-pki-defs.h>
  31#include <mach/cvmx-xcv-defs.h>
  32
  33#include <mach/cvmx-helper.h>
  34#include <mach/cvmx-helper-board.h>
  35#include <mach/cvmx-helper-cfg.h>
  36
  37/**
  38 * @INTERNAL
  39 * Perform initialization required only once for an SGMII port.
  40 *
  41 * @param interface to init
  42 * @param index     Index of prot on the interface
  43 *
  44 * @return Zero on success, negative on failure
  45 */
  46static int __cvmx_helper_sgmii_hardware_init_one_time(int interface, int index)
  47{
  48        const u64 clock_mhz = 1200; /* todo: fixme */
  49        union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
  50        union cvmx_pcsx_linkx_timer_count_reg pcsx_linkx_timer_count_reg;
  51        union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
  52
  53        if (!cvmx_helper_is_port_valid(interface, index))
  54                return 0;
  55
  56        /* Disable GMX */
  57        gmxx_prtx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
  58        gmxx_prtx_cfg.s.en = 0;
  59        csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
  60
  61        /*
  62         * Write PCS*_LINK*_TIMER_COUNT_REG[COUNT] with the
  63         * appropriate value. 1000BASE-X specifies a 10ms
  64         * interval. SGMII specifies a 1.6ms interval.
  65         */
  66        pcsx_miscx_ctl_reg.u64 =
  67                csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
  68        /* Adjust the MAC mode if requested by device tree */
  69        pcsx_miscx_ctl_reg.s.mac_phy =
  70                cvmx_helper_get_mac_phy_mode(interface, index);
  71        pcsx_miscx_ctl_reg.s.mode =
  72                cvmx_helper_get_1000x_mode(interface, index);
  73        csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
  74               pcsx_miscx_ctl_reg.u64);
  75
  76        pcsx_linkx_timer_count_reg.u64 =
  77                csr_rd(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface));
  78        if (pcsx_miscx_ctl_reg.s.mode)
  79                /* 1000BASE-X */
  80                pcsx_linkx_timer_count_reg.s.count =
  81                        (10000ull * clock_mhz) >> 10;
  82        else
  83                /* SGMII */
  84                pcsx_linkx_timer_count_reg.s.count =
  85                        (1600ull * clock_mhz) >> 10;
  86
  87        csr_wr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface),
  88               pcsx_linkx_timer_count_reg.u64);
  89
  90        /*
  91         * Write the advertisement register to be used as the
  92         * tx_Config_Reg<D15:D0> of the autonegotiation.  In
  93         * 1000BASE-X mode, tx_Config_Reg<D15:D0> is PCS*_AN*_ADV_REG.
  94         * In SGMII PHY mode, tx_Config_Reg<D15:D0> is
  95         * PCS*_SGM*_AN_ADV_REG.  In SGMII MAC mode,
  96         * tx_Config_Reg<D15:D0> is the fixed value 0x4001, so this
  97         * step can be skipped.
  98         */
  99        if (pcsx_miscx_ctl_reg.s.mode) {
 100                /* 1000BASE-X */
 101                union cvmx_pcsx_anx_adv_reg pcsx_anx_adv_reg;
 102
 103                pcsx_anx_adv_reg.u64 =
 104                        csr_rd(CVMX_PCSX_ANX_ADV_REG(index, interface));
 105                pcsx_anx_adv_reg.s.rem_flt = 0;
 106                pcsx_anx_adv_reg.s.pause = 3;
 107                pcsx_anx_adv_reg.s.hfd = 1;
 108                pcsx_anx_adv_reg.s.fd = 1;
 109                csr_wr(CVMX_PCSX_ANX_ADV_REG(index, interface),
 110                       pcsx_anx_adv_reg.u64);
 111        } else {
 112                if (pcsx_miscx_ctl_reg.s.mac_phy) {
 113                        /* PHY Mode */
 114                        union cvmx_pcsx_sgmx_an_adv_reg pcsx_sgmx_an_adv_reg;
 115
 116                        pcsx_sgmx_an_adv_reg.u64 = csr_rd(
 117                                CVMX_PCSX_SGMX_AN_ADV_REG(index, interface));
 118                        pcsx_sgmx_an_adv_reg.s.dup = 1;
 119                        pcsx_sgmx_an_adv_reg.s.speed = 2;
 120                        csr_wr(CVMX_PCSX_SGMX_AN_ADV_REG(index, interface),
 121                               pcsx_sgmx_an_adv_reg.u64);
 122                } else {
 123                        /* MAC Mode - Nothing to do */
 124                }
 125        }
 126        return 0;
 127}
 128
 129static int __cvmx_helper_need_g15618(void)
 130{
 131        if (OCTEON_IS_MODEL(OCTEON_CN63XX) ||
 132            OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X) ||
 133            OCTEON_IS_MODEL(OCTEON_CN68XX))
 134                return 1;
 135        else
 136                return 0;
 137}
 138
 139/**
 140 * @INTERNAL
 141 * Initialize the SERTES link for the first time or after a loss
 142 * of link.
 143 *
 144 * @param interface to init
 145 * @param index     Index of prot on the interface
 146 *
 147 * @return Zero on success, negative on failure
 148 */
 149static int __cvmx_helper_sgmii_hardware_init_link(int interface, int index)
 150{
 151        union cvmx_pcsx_mrx_control_reg control_reg;
 152        union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
 153        bool phy_mode;
 154        bool an_disable; /** Disable autonegotiation */
 155        bool mode_1000x; /** 1000Base-X mode */
 156
 157        if (!cvmx_helper_is_port_valid(interface, index))
 158                return 0;
 159
 160        /*
 161         * Take PCS through a reset sequence.
 162         * PCS*_MR*_CONTROL_REG[PWR_DN] should be cleared to zero.
 163         * Write PCS*_MR*_CONTROL_REG[RESET]=1 (while not changing the
 164         * value of the other PCS*_MR*_CONTROL_REG bits).  Read
 165         * PCS*_MR*_CONTROL_REG[RESET] until it changes value to
 166         * zero.
 167         */
 168        control_reg.u64 = csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
 169
 170        /*
 171         * Errata G-15618 requires disabling PCS soft reset in CN63XX
 172         * pass upto 2.1.
 173         */
 174        if (!__cvmx_helper_need_g15618()) {
 175                control_reg.s.reset = 1;
 176                csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
 177                       control_reg.u64);
 178                if (CVMX_WAIT_FOR_FIELD64(
 179                            CVMX_PCSX_MRX_CONTROL_REG(index, interface),
 180                            cvmx_pcsx_mrx_control_reg_t, reset, ==, 0, 10000)) {
 181                        debug("SGMII%x: Timeout waiting for port %d to finish reset\n",
 182                              interface, index);
 183                        return -1;
 184                }
 185        }
 186
 187        /*
 188         * Write PCS*_MR*_CONTROL_REG[RST_AN]=1 to ensure a fresh
 189         * sgmii negotiation starts.
 190         */
 191        phy_mode = cvmx_helper_get_mac_phy_mode(interface, index);
 192        an_disable = (phy_mode ||
 193                      !cvmx_helper_get_port_autonegotiation(interface, index));
 194
 195        control_reg.s.an_en = !an_disable;
 196
 197        /* Force a PCS reset by powering down the PCS interface
 198         * This is needed to deal with broken Qualcomm/Atheros PHYs and switches
 199         * which never recover if PCS is not power cycled.  The alternative
 200         * is to power cycle or hardware reset the Qualcomm devices whenever
 201         * SGMII is initialized.
 202         *
 203         * This is needed for the QCA8033 PHYs as well as the QCA833X switches
 204         * to work.  The QCA8337 switch has additional SGMII problems and is
 205         * best avoided if at all possible.  Failure to power cycle PCS prevents
 206         * any traffic from flowing between Octeon and Qualcomm devices if there
 207         * is a warm reset.  Even a software reset to the Qualcomm device will
 208         * not work.
 209         *
 210         * Note that this problem has been reported between Qualcomm and other
 211         * vendor's processors as well so this problem is not unique to
 212         * Qualcomm and Octeon.
 213         *
 214         * Power cycling PCS doesn't hurt anything with non-Qualcomm devices
 215         * other than adding a 25ms delay during initialization.
 216         */
 217        control_reg.s.pwr_dn = 1;
 218        csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), control_reg.u64);
 219        csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
 220
 221        /* 25ms should be enough, 10ms is too short */
 222        mdelay(25);
 223
 224        control_reg.s.pwr_dn = 0;
 225        csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), control_reg.u64);
 226
 227        /* The Cortina PHY runs in 1000base-X mode */
 228        mode_1000x = cvmx_helper_get_1000x_mode(interface, index);
 229        pcsx_miscx_ctl_reg.u64 =
 230                csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
 231        pcsx_miscx_ctl_reg.s.mode = mode_1000x;
 232        pcsx_miscx_ctl_reg.s.mac_phy = phy_mode;
 233        csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
 234               pcsx_miscx_ctl_reg.u64);
 235        if (an_disable)
 236                /* In PHY mode we can't query the link status so we just
 237                 * assume that the link is up.
 238                 */
 239                return 0;
 240
 241        /*
 242         * Wait for PCS*_MR*_STATUS_REG[AN_CPT] to be set, indicating
 243         * that sgmii autonegotiation is complete. In MAC mode this
 244         * isn't an ethernet link, but a link between Octeon and the
 245         * PHY.
 246         */
 247        if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSX_MRX_STATUS_REG(index, interface),
 248                                  union cvmx_pcsx_mrx_status_reg, an_cpt, ==, 1,
 249                                  10000)) {
 250                debug("SGMII%x: Port %d link timeout\n", interface, index);
 251                return -1;
 252        }
 253        return 0;
 254}
 255
 256/**
 257 * @INTERNAL
 258 * Configure an SGMII link to the specified speed after the SERTES
 259 * link is up.
 260 *
 261 * @param interface to init
 262 * @param index     Index of prot on the interface
 263 * @param link_info Link state to configure
 264 *
 265 * @return Zero on success, negative on failure
 266 */
 267static int
 268__cvmx_helper_sgmii_hardware_init_link_speed(int interface, int index,
 269                                             cvmx_helper_link_info_t link_info)
 270{
 271        int is_enabled;
 272        union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
 273        union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
 274
 275        if (!cvmx_helper_is_port_valid(interface, index))
 276                return 0;
 277
 278        /* Disable GMX before we make any changes. Remember the enable state */
 279        gmxx_prtx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
 280        is_enabled = gmxx_prtx_cfg.s.en;
 281        gmxx_prtx_cfg.s.en = 0;
 282        csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
 283
 284        /* Wait for GMX to be idle */
 285        if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface),
 286                                  cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1,
 287                                  10000) ||
 288            CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface),
 289                                  cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1,
 290                                  10000)) {
 291                debug("SGMII%d: Timeout waiting for port %d to be idle\n",
 292                      interface, index);
 293                return -1;
 294        }
 295
 296        /* Read GMX CFG again to make sure the disable completed */
 297        gmxx_prtx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
 298
 299        /*
 300         * Get the misc control for PCS. We will need to set the
 301         * duplication amount.
 302         */
 303        pcsx_miscx_ctl_reg.u64 =
 304                csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
 305
 306        /*
 307         * Use GMXENO to force the link down if the status we get says
 308         * it should be down.
 309         */
 310        pcsx_miscx_ctl_reg.s.gmxeno = !link_info.s.link_up;
 311
 312        /* Only change the duplex setting if the link is up */
 313        if (link_info.s.link_up)
 314                gmxx_prtx_cfg.s.duplex = link_info.s.full_duplex;
 315
 316        /* Do speed based setting for GMX */
 317        switch (link_info.s.speed) {
 318        case 10:
 319                gmxx_prtx_cfg.s.speed = 0;
 320                gmxx_prtx_cfg.s.speed_msb = 1;
 321                gmxx_prtx_cfg.s.slottime = 0;
 322                /* Setting from GMX-603 */
 323                pcsx_miscx_ctl_reg.s.samp_pt = 25;
 324                csr_wr(CVMX_GMXX_TXX_SLOT(index, interface), 64);
 325                csr_wr(CVMX_GMXX_TXX_BURST(index, interface), 0);
 326                break;
 327        case 100:
 328                gmxx_prtx_cfg.s.speed = 0;
 329                gmxx_prtx_cfg.s.speed_msb = 0;
 330                gmxx_prtx_cfg.s.slottime = 0;
 331                pcsx_miscx_ctl_reg.s.samp_pt = 0x5;
 332                csr_wr(CVMX_GMXX_TXX_SLOT(index, interface), 64);
 333                csr_wr(CVMX_GMXX_TXX_BURST(index, interface), 0);
 334                break;
 335        case 1000:
 336                gmxx_prtx_cfg.s.speed = 1;
 337                gmxx_prtx_cfg.s.speed_msb = 0;
 338                gmxx_prtx_cfg.s.slottime = 1;
 339                pcsx_miscx_ctl_reg.s.samp_pt = 1;
 340                csr_wr(CVMX_GMXX_TXX_SLOT(index, interface), 512);
 341                if (gmxx_prtx_cfg.s.duplex)
 342                        /* full duplex */
 343                        csr_wr(CVMX_GMXX_TXX_BURST(index, interface), 0);
 344                else
 345                        /* half duplex */
 346                        csr_wr(CVMX_GMXX_TXX_BURST(index, interface), 8192);
 347                break;
 348        default:
 349                break;
 350        }
 351
 352        /* Write the new misc control for PCS */
 353        csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
 354               pcsx_miscx_ctl_reg.u64);
 355
 356        /* Write the new GMX settings with the port still disabled */
 357        csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
 358
 359        /* Read GMX CFG again to make sure the config completed */
 360        gmxx_prtx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
 361
 362        /* Restore the enabled / disabled state */
 363        gmxx_prtx_cfg.s.en = is_enabled;
 364        csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
 365
 366        return 0;
 367}
 368
 369/**
 370 * @INTERNAL
 371 * Bring up the SGMII interface to be ready for packet I/O but
 372 * leave I/O disabled using the GMX override. This function
 373 * follows the bringup documented in 10.6.3 of the manual.
 374 *
 375 * @param interface to bringup
 376 * @param num_ports Number of ports on the interface
 377 *
 378 * @return Zero on success, negative on failure
 379 */
 380static int __cvmx_helper_sgmii_hardware_init(int interface, int num_ports)
 381{
 382        int index;
 383        int do_link_set = 1;
 384
 385        /*
 386         * CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis
 387         * be programmed.
 388         */
 389        if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) {
 390                union cvmx_ciu_qlm2 ciu_qlm;
 391
 392                ciu_qlm.u64 = csr_rd(CVMX_CIU_QLM2);
 393                ciu_qlm.s.txbypass = 1;
 394                ciu_qlm.s.txdeemph = 0xf;
 395                ciu_qlm.s.txmargin = 0xd;
 396                csr_wr(CVMX_CIU_QLM2, ciu_qlm.u64);
 397        }
 398
 399        /*
 400         * CN63XX Pass 2.x errata G-15273 requires the QLM De-emphasis
 401         * be programmed when using a 156.25Mhz ref clock.
 402         */
 403        if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_X)) {
 404                /* Read the QLM speed pins */
 405                union cvmx_mio_rst_boot mio_rst_boot;
 406
 407                mio_rst_boot.u64 = csr_rd(CVMX_MIO_RST_BOOT);
 408
 409                if (mio_rst_boot.cn63xx.qlm2_spd == 4) {
 410                        union cvmx_ciu_qlm2 ciu_qlm;
 411
 412                        ciu_qlm.u64 = csr_rd(CVMX_CIU_QLM2);
 413                        ciu_qlm.s.txbypass = 1;
 414                        ciu_qlm.s.txdeemph = 0x0;
 415                        ciu_qlm.s.txmargin = 0xf;
 416                        csr_wr(CVMX_CIU_QLM2, ciu_qlm.u64);
 417                }
 418        }
 419
 420        __cvmx_helper_setup_gmx(interface, num_ports);
 421
 422        for (index = 0; index < num_ports; index++) {
 423                int ipd_port = cvmx_helper_get_ipd_port(interface, index);
 424
 425                if (!cvmx_helper_is_port_valid(interface, index))
 426                        continue;
 427                __cvmx_helper_sgmii_hardware_init_one_time(interface, index);
 428                if (do_link_set)
 429                        __cvmx_helper_sgmii_link_set(ipd_port,
 430                                                     __cvmx_helper_sgmii_link_get(ipd_port));
 431        }
 432
 433        return 0;
 434}
 435
 436int __cvmx_helper_sgmii_enumerate(int xiface)
 437{
 438        if (OCTEON_IS_MODEL(OCTEON_CNF71XX))
 439                return 2;
 440        if (OCTEON_IS_MODEL(OCTEON_CN70XX)) {
 441                struct cvmx_xiface xi =
 442                        cvmx_helper_xiface_to_node_interface(xiface);
 443                enum cvmx_qlm_mode qlm_mode =
 444                        cvmx_qlm_get_dlm_mode(0, xi.interface);
 445
 446                if (qlm_mode == CVMX_QLM_MODE_SGMII)
 447                        return 1;
 448                else if (qlm_mode == CVMX_QLM_MODE_QSGMII)
 449                        return 4;
 450                return 0;
 451        }
 452        return 4;
 453}
 454
 455/**
 456 * @INTERNAL
 457 * Probe a SGMII interface and determine the number of ports
 458 * connected to it. The SGMII interface should still be down after
 459 * this call.
 460 *
 461 * @param xiface Interface to probe
 462 *
 463 * @return Number of ports on the interface. Zero to disable.
 464 */
 465int __cvmx_helper_sgmii_probe(int xiface)
 466{
 467        struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
 468        int interface = xi.interface;
 469        union cvmx_gmxx_inf_mode mode;
 470        int ports;
 471
 472        /*
 473         * Check if QLM is configured correct for SGMII, verify the
 474         * speed as well as mode.
 475         */
 476        if (OCTEON_IS_OCTEON2()) {
 477                int qlm = cvmx_qlm_interface(xiface);
 478
 479                if (cvmx_qlm_get_mode(qlm) != CVMX_QLM_MODE_SGMII)
 480                        return 0;
 481        }
 482
 483        /* Do not enable the interface if is not in SGMII mode */
 484        ports = __cvmx_helper_sgmii_enumerate(xiface);
 485
 486        if (ports <= 0)
 487                return 0;
 488
 489        /*
 490         * Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the
 491         * interface needs to be enabled before IPD otherwise per port
 492         * backpressure may not work properly.
 493         */
 494        mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(interface));
 495        mode.s.en = 1;
 496        csr_wr(CVMX_GMXX_INF_MODE(interface), mode.u64);
 497
 498        return ports;
 499}
 500
 501/**
 502 * @INTERNAL
 503 * Bringup and enable a SGMII interface. After this call packet
 504 * I/O should be fully functional. This is called with IPD
 505 * enabled but PKO disabled.
 506 *
 507 * @param xiface Interface to bring up
 508 *
 509 * @return Zero on success, negative on failure
 510 */
 511int __cvmx_helper_sgmii_enable(int xiface)
 512{
 513        int num_ports = cvmx_helper_ports_on_interface(xiface);
 514        struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
 515        int interface = xi.interface;
 516        int index;
 517
 518        /* Setup PKND and BPID */
 519        if (octeon_has_feature(OCTEON_FEATURE_PKND)) {
 520                for (index = 0; index < num_ports; index++) {
 521                        union cvmx_gmxx_bpid_msk bpid_msk;
 522                        union cvmx_gmxx_bpid_mapx bpid_map;
 523                        union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
 524
 525                        if (!cvmx_helper_is_port_valid(interface, index))
 526                                continue;
 527                        /* Setup PKIND */
 528                        gmxx_prtx_cfg.u64 =
 529                                csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
 530                        gmxx_prtx_cfg.s.pknd =
 531                                cvmx_helper_get_pknd(interface, index);
 532                        csr_wr(CVMX_GMXX_PRTX_CFG(index, interface),
 533                               gmxx_prtx_cfg.u64);
 534
 535                        /* Setup BPID */
 536                        bpid_map.u64 =
 537                                csr_rd(CVMX_GMXX_BPID_MAPX(index, interface));
 538                        bpid_map.s.val = 1;
 539                        bpid_map.s.bpid =
 540                                cvmx_helper_get_bpid(interface, index);
 541                        csr_wr(CVMX_GMXX_BPID_MAPX(index, interface),
 542                               bpid_map.u64);
 543
 544                        bpid_msk.u64 = csr_rd(CVMX_GMXX_BPID_MSK(interface));
 545                        bpid_msk.s.msk_or |= (1 << index);
 546                        bpid_msk.s.msk_and &= ~(1 << index);
 547                        csr_wr(CVMX_GMXX_BPID_MSK(interface), bpid_msk.u64);
 548                }
 549        }
 550
 551        __cvmx_helper_sgmii_hardware_init(interface, num_ports);
 552
 553        /* CN68XX adds the padding and FCS in PKO, not GMX */
 554        if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
 555                union cvmx_gmxx_txx_append gmxx_txx_append_cfg;
 556
 557                for (index = 0; index < num_ports; index++) {
 558                        if (!cvmx_helper_is_port_valid(interface, index))
 559                                continue;
 560                        gmxx_txx_append_cfg.u64 =
 561                                csr_rd(CVMX_GMXX_TXX_APPEND(index, interface));
 562                        gmxx_txx_append_cfg.s.fcs = 0;
 563                        gmxx_txx_append_cfg.s.pad = 0;
 564                        csr_wr(CVMX_GMXX_TXX_APPEND(index, interface),
 565                               gmxx_txx_append_cfg.u64);
 566                }
 567        }
 568
 569        /* Enable running disparity check for QSGMII interface */
 570        if (OCTEON_IS_MODEL(OCTEON_CN70XX) && num_ports > 1) {
 571                union cvmx_gmxx_qsgmii_ctl qsgmii_ctl;
 572
 573                qsgmii_ctl.u64 = 0;
 574                qsgmii_ctl.s.disparity = 1;
 575                csr_wr(CVMX_GMXX_QSGMII_CTL(interface), qsgmii_ctl.u64);
 576        }
 577
 578        for (index = 0; index < num_ports; index++) {
 579                union cvmx_gmxx_txx_append append_cfg;
 580                union cvmx_gmxx_txx_sgmii_ctl sgmii_ctl;
 581                union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
 582
 583                if (!cvmx_helper_is_port_valid(interface, index))
 584                        continue;
 585                /*
 586                 * Clear the align bit if preamble is set to attain
 587                 * maximum tx rate.
 588                 */
 589                append_cfg.u64 = csr_rd(CVMX_GMXX_TXX_APPEND(index, interface));
 590                sgmii_ctl.u64 =
 591                        csr_rd(CVMX_GMXX_TXX_SGMII_CTL(index, interface));
 592                sgmii_ctl.s.align = append_cfg.s.preamble ? 0 : 1;
 593                csr_wr(CVMX_GMXX_TXX_SGMII_CTL(index, interface),
 594                       sgmii_ctl.u64);
 595
 596                gmxx_prtx_cfg.u64 =
 597                        csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
 598                gmxx_prtx_cfg.s.en = 1;
 599                csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
 600        }
 601        return 0;
 602}
 603
 604/**
 605 * @INTERNAL
 606 * Return the link state of an IPD/PKO port as returned by
 607 * auto negotiation. The result of this function may not match
 608 * Octeon's link config if auto negotiation has changed since
 609 * the last call to cvmx_helper_link_set().
 610 *
 611 * @param ipd_port IPD/PKO port to query
 612 *
 613 * @return Link state
 614 */
 615cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port)
 616{
 617        cvmx_helper_link_info_t result;
 618        union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
 619        int interface = cvmx_helper_get_interface_num(ipd_port);
 620        int index = cvmx_helper_get_interface_index_num(ipd_port);
 621        union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg;
 622        int speed = 1000;
 623        int qlm;
 624
 625        result.u64 = 0;
 626
 627        if (!cvmx_helper_is_port_valid(interface, index))
 628                return result;
 629
 630        if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
 631                union cvmx_gmxx_inf_mode inf_mode;
 632
 633                inf_mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(interface));
 634                if (inf_mode.s.rate & (1 << index))
 635                        speed = 2500;
 636                else
 637                        speed = 1000;
 638        } else if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
 639                qlm = cvmx_qlm_interface(interface);
 640                speed = cvmx_qlm_get_gbaud_mhz(qlm) * 8 / 10;
 641        } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
 642                speed = cvmx_qlm_get_gbaud_mhz(0) * 8 / 10;
 643        } else if (OCTEON_IS_MODEL(OCTEON_CN70XX)) {
 644                speed = cvmx_qlm_get_gbaud_mhz(0) * 8 / 10;
 645                if (cvmx_qlm_get_dlm_mode(0, interface) == CVMX_QLM_MODE_SGMII)
 646                        speed >>= 1;
 647                else
 648                        speed >>= 2;
 649        }
 650
 651        pcsx_mrx_control_reg.u64 =
 652                csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
 653        if (pcsx_mrx_control_reg.s.loopbck1) {
 654                /* Force 1Gbps full duplex link for internal loopback */
 655                result.s.link_up = 1;
 656                result.s.full_duplex = 1;
 657                result.s.speed = speed;
 658                return result;
 659        }
 660
 661        pcsx_miscx_ctl_reg.u64 =
 662                csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
 663        if (pcsx_miscx_ctl_reg.s.mac_phy ||
 664            cvmx_helper_get_port_force_link_up(interface, index)) {
 665                /* PHY Mode */
 666                /* Note that this also works for 1000base-X mode */
 667
 668                result.s.speed = speed;
 669                result.s.full_duplex = 1;
 670                result.s.link_up = 1;
 671                return result;
 672        }
 673
 674        /* MAC Mode */
 675        return __cvmx_helper_board_link_get(ipd_port);
 676}
 677
 678/**
 679 * @INTERNAL
 680 * Configure an IPD/PKO port for the specified link state. This
 681 * function does not influence auto negotiation at the PHY level.
 682 * The passed link state must always match the link state returned
 683 * by cvmx_helper_link_get(). It is normally best to use
 684 * cvmx_helper_link_autoconf() instead.
 685 *
 686 * @param ipd_port  IPD/PKO port to configure
 687 * @param link_info The new link state
 688 *
 689 * @return Zero on success, negative on failure
 690 */
 691int __cvmx_helper_sgmii_link_set(int ipd_port,
 692                                 cvmx_helper_link_info_t link_info)
 693{
 694        union cvmx_pcsx_mrx_control_reg control_reg;
 695        int interface = cvmx_helper_get_interface_num(ipd_port);
 696        int index = cvmx_helper_get_interface_index_num(ipd_port);
 697
 698        if (!cvmx_helper_is_port_valid(interface, index))
 699                return 0;
 700
 701        /* For some devices, i.e. the Qualcomm QCA8337 switch we need to power
 702         * down the PCS interface when the link goes down and power it back
 703         * up when the link returns.
 704         */
 705        if (link_info.s.link_up || !__cvmx_helper_need_g15618()) {
 706                __cvmx_helper_sgmii_hardware_init_link(interface, index);
 707        } else {
 708                union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
 709
 710                pcsx_miscx_ctl_reg.u64 =
 711                        csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
 712
 713                /* Disable autonegotiation when MAC mode is enabled or
 714                 * autonegotiation is disabled.
 715                 */
 716                control_reg.u64 =
 717                        csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
 718                if (pcsx_miscx_ctl_reg.s.mac_phy == 0 ||
 719                    !cvmx_helper_get_port_autonegotiation(interface, index)) {
 720                        control_reg.s.an_en = 0;
 721                        control_reg.s.spdmsb = 1;
 722                        control_reg.s.spdlsb = 0;
 723                        control_reg.s.dup = 1;
 724                }
 725                csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
 726                       control_reg.u64);
 727                csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
 728                /*
 729                 * Use GMXENO to force the link down it will get
 730                 * reenabled later...
 731                 */
 732                pcsx_miscx_ctl_reg.s.gmxeno = 1;
 733                csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
 734                       pcsx_miscx_ctl_reg.u64);
 735                csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
 736                return 0;
 737        }
 738        return __cvmx_helper_sgmii_hardware_init_link_speed(interface, index,
 739                                                            link_info);
 740}
 741
 742/**
 743 * @INTERNAL
 744 * Configure a port for internal and/or external loopback. Internal loopback
 745 * causes packets sent by the port to be received by Octeon. External loopback
 746 * causes packets received from the wire to sent out again.
 747 *
 748 * @param ipd_port IPD/PKO port to loopback.
 749 * @param enable_internal
 750 *                 Non zero if you want internal loopback
 751 * @param enable_external
 752 *                 Non zero if you want external loopback
 753 *
 754 * @return Zero on success, negative on failure.
 755 */
 756int __cvmx_helper_sgmii_configure_loopback(int ipd_port, int enable_internal,
 757                                           int enable_external)
 758{
 759        int interface = cvmx_helper_get_interface_num(ipd_port);
 760        int index = cvmx_helper_get_interface_index_num(ipd_port);
 761        union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg;
 762        union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
 763
 764        if (!cvmx_helper_is_port_valid(interface, index))
 765                return 0;
 766
 767        pcsx_mrx_control_reg.u64 =
 768                csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
 769        pcsx_mrx_control_reg.s.loopbck1 = enable_internal;
 770        csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
 771               pcsx_mrx_control_reg.u64);
 772
 773        pcsx_miscx_ctl_reg.u64 =
 774                csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
 775        pcsx_miscx_ctl_reg.s.loopbck2 = enable_external;
 776        csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
 777               pcsx_miscx_ctl_reg.u64);
 778
 779        __cvmx_helper_sgmii_hardware_init_link(interface, index);
 780        return 0;
 781}
 782