uboot/board/freescale/t1040qds/eth.c
<<
>>
Prefs
   1/*
   2 * Copyright 2013 Freescale Semiconductor, Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7/*
   8 * The RGMII PHYs are provided by the two on-board PHY connected to
   9 * dTSEC instances 4 and 5. The SGMII PHYs are provided by one on-board
  10 * PHY or by the standard four-port SGMII riser card (VSC).
  11 */
  12
  13#include <common.h>
  14#include <netdev.h>
  15#include <asm/fsl_serdes.h>
  16#include <asm/immap_85xx.h>
  17#include <fm_eth.h>
  18#include <fsl_mdio.h>
  19#include <malloc.h>
  20#include <fsl_dtsec.h>
  21#include <vsc9953.h>
  22
  23#include "../common/fman.h"
  24#include "../common/qixis.h"
  25
  26#include "t1040qds_qixis.h"
  27
  28#ifdef CONFIG_FMAN_ENET
  29 /* - In T1040 there are only 8 SERDES lanes, spread across 2 SERDES banks.
  30 *   Bank 1 -> Lanes A, B, C, D
  31 *   Bank 2 -> Lanes E, F, G, H
  32 */
  33
  34 /* Mapping of 8 SERDES lanes to T1040 QDS board slots. A value of '0' here
  35  * means that the mapping must be determined dynamically, or that the lane
  36  * maps to something other than a board slot.
  37  */
  38static u8 lane_to_slot[] = {
  39        0, 0, 0, 0, 0, 0, 0, 0
  40};
  41
  42/* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs
  43 * housed.
  44 */
  45static int riser_phy_addr[] = {
  46        CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR,
  47        CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR,
  48        CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR,
  49        CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR,
  50};
  51
  52/* Slot2 does not have EMI connections */
  53#define EMI_NONE        0xFFFFFFFF
  54#define EMI1_RGMII0     0
  55#define EMI1_RGMII1     1
  56#define EMI1_SLOT1      2
  57#define EMI1_SLOT3      3
  58#define EMI1_SLOT4      4
  59#define EMI1_SLOT5      5
  60#define EMI1_SLOT6      6
  61#define EMI1_SLOT7      7
  62#define EMI2            8
  63
  64static int mdio_mux[NUM_FM_PORTS];
  65
  66static const char * const mdio_names[] = {
  67        "T1040_QDS_MDIO0",
  68        "T1040_QDS_MDIO1",
  69        "T1040_QDS_MDIO2",
  70        "T1040_QDS_MDIO3",
  71        "T1040_QDS_MDIO4",
  72        "T1040_QDS_MDIO5",
  73        "T1040_QDS_MDIO6",
  74        "T1040_QDS_MDIO7",
  75};
  76
  77struct t1040_qds_mdio {
  78        u8 muxval;
  79        struct mii_dev *realbus;
  80};
  81
  82static const char *t1040_qds_mdio_name_for_muxval(u8 muxval)
  83{
  84        return mdio_names[muxval];
  85}
  86
  87struct mii_dev *mii_dev_for_muxval(u8 muxval)
  88{
  89        struct mii_dev *bus;
  90        const char *name = t1040_qds_mdio_name_for_muxval(muxval);
  91
  92        if (!name) {
  93                printf("No bus for muxval %x\n", muxval);
  94                return NULL;
  95        }
  96
  97        bus = miiphy_get_dev_by_name(name);
  98
  99        if (!bus) {
 100                printf("No bus by name %s\n", name);
 101                return NULL;
 102        }
 103
 104        return bus;
 105}
 106
 107static void t1040_qds_mux_mdio(u8 muxval)
 108{
 109        u8 brdcfg4;
 110        if (muxval <= 7) {
 111                brdcfg4 = QIXIS_READ(brdcfg[4]);
 112                brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
 113                brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT);
 114                QIXIS_WRITE(brdcfg[4], brdcfg4);
 115        }
 116}
 117
 118static int t1040_qds_mdio_read(struct mii_dev *bus, int addr, int devad,
 119                                int regnum)
 120{
 121        struct t1040_qds_mdio *priv = bus->priv;
 122
 123        t1040_qds_mux_mdio(priv->muxval);
 124
 125        return priv->realbus->read(priv->realbus, addr, devad, regnum);
 126}
 127
 128static int t1040_qds_mdio_write(struct mii_dev *bus, int addr, int devad,
 129                                int regnum, u16 value)
 130{
 131        struct t1040_qds_mdio *priv = bus->priv;
 132
 133        t1040_qds_mux_mdio(priv->muxval);
 134
 135        return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
 136}
 137
 138static int t1040_qds_mdio_reset(struct mii_dev *bus)
 139{
 140        struct t1040_qds_mdio *priv = bus->priv;
 141
 142        return priv->realbus->reset(priv->realbus);
 143}
 144
 145static int t1040_qds_mdio_init(char *realbusname, u8 muxval)
 146{
 147        struct t1040_qds_mdio *pmdio;
 148        struct mii_dev *bus = mdio_alloc();
 149
 150        if (!bus) {
 151                printf("Failed to allocate t1040_qds MDIO bus\n");
 152                return -1;
 153        }
 154
 155        pmdio = malloc(sizeof(*pmdio));
 156        if (!pmdio) {
 157                printf("Failed to allocate t1040_qds private data\n");
 158                free(bus);
 159                return -1;
 160        }
 161
 162        bus->read = t1040_qds_mdio_read;
 163        bus->write = t1040_qds_mdio_write;
 164        bus->reset = t1040_qds_mdio_reset;
 165        strcpy(bus->name, t1040_qds_mdio_name_for_muxval(muxval));
 166
 167        pmdio->realbus = miiphy_get_dev_by_name(realbusname);
 168
 169        if (!pmdio->realbus) {
 170                printf("No bus with name %s\n", realbusname);
 171                free(bus);
 172                free(pmdio);
 173                return -1;
 174        }
 175
 176        pmdio->muxval = muxval;
 177        bus->priv = pmdio;
 178
 179        return mdio_register(bus);
 180}
 181
 182/*
 183 * Initialize the lane_to_slot[] array.
 184 *
 185 * On the T1040QDS board the mapping is controlled by ?? register.
 186 */
 187static void initialize_lane_to_slot(void)
 188{
 189        ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
 190        int serdes1_prtcl = (in_be32(&gur->rcwsr[4]) &
 191                                FSL_CORENET2_RCWSR4_SRDS1_PRTCL)
 192                >> FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
 193
 194        QIXIS_WRITE(cms[0], 0x07);
 195
 196        switch (serdes1_prtcl) {
 197        case 0x60:
 198        case 0x66:
 199        case 0x67:
 200        case 0x69:
 201                lane_to_slot[1] = 7;
 202                lane_to_slot[2] = 6;
 203                lane_to_slot[3] = 5;
 204                break;
 205        case 0x86:
 206                lane_to_slot[1] = 7;
 207                lane_to_slot[2] = 7;
 208                lane_to_slot[3] = 7;
 209                break;
 210        case 0x87:
 211                lane_to_slot[1] = 7;
 212                lane_to_slot[2] = 7;
 213                lane_to_slot[3] = 7;
 214                lane_to_slot[7] = 7;
 215                break;
 216        case 0x89:
 217                lane_to_slot[1] = 7;
 218                lane_to_slot[2] = 7;
 219                lane_to_slot[3] = 7;
 220                lane_to_slot[6] = 7;
 221                lane_to_slot[7] = 7;
 222                break;
 223        case 0x8d:
 224                lane_to_slot[1] = 7;
 225                lane_to_slot[2] = 7;
 226                lane_to_slot[3] = 7;
 227                lane_to_slot[5] = 3;
 228                lane_to_slot[6] = 3;
 229                lane_to_slot[7] = 3;
 230                break;
 231        case 0x8F:
 232        case 0x85:
 233                lane_to_slot[1] = 7;
 234                lane_to_slot[2] = 6;
 235                lane_to_slot[3] = 5;
 236                lane_to_slot[6] = 3;
 237                lane_to_slot[7] = 3;
 238                break;
 239        case 0xA5:
 240                lane_to_slot[1] = 7;
 241                lane_to_slot[6] = 3;
 242                lane_to_slot[7] = 3;
 243                break;
 244        case 0xA7:
 245                lane_to_slot[1] = 7;
 246                lane_to_slot[2] = 6;
 247                lane_to_slot[3] = 5;
 248                lane_to_slot[7] = 7;
 249                break;
 250        case 0xAA:
 251                lane_to_slot[1] = 7;
 252                lane_to_slot[6] = 7;
 253                lane_to_slot[7] = 7;
 254                break;
 255        case 0x40:
 256                lane_to_slot[2] = 7;
 257                lane_to_slot[3] = 7;
 258                break;
 259        default:
 260                printf("qds: Fman: Unsupported SerDes Protocol 0x%02x\n",
 261                       serdes1_prtcl);
 262                break;
 263        }
 264}
 265
 266/*
 267 * Given the following ...
 268 *
 269 * 1) A pointer to an Fman Ethernet node (as identified by the 'compat'
 270 * compatible string and 'addr' physical address)
 271 *
 272 * 2) An Fman port
 273 *
 274 * ... update the phy-handle property of the Ethernet node to point to the
 275 * right PHY. This assumes that we already know the PHY for each port.
 276 *
 277 * The offset of the Fman Ethernet node is also passed in for convenience, but
 278 * it is not used, and we recalculate the offset anyway.
 279 *
 280 * Note that what we call "Fman ports" (enum fm_port) is really an Fman MAC.
 281 * Inside the Fman, "ports" are things that connect to MACs. We only call them
 282 * ports in U-Boot because on previous Ethernet devices (e.g. Gianfar), MACs
 283 * and ports are the same thing.
 284 *
 285 */
 286void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
 287                              enum fm_port port, int offset)
 288{
 289        phy_interface_t intf = fm_info_get_enet_if(port);
 290        char phy[16];
 291
 292        /* The RGMII PHY is identified by the MAC connected to it */
 293        if (intf == PHY_INTERFACE_MODE_RGMII) {
 294                sprintf(phy, "rgmii_phy%u", port == FM1_DTSEC4 ? 1 : 2);
 295                fdt_set_phy_handle(fdt, compat, addr, phy);
 296        }
 297
 298        /* The SGMII PHY is identified by the MAC connected to it */
 299        if (intf == PHY_INTERFACE_MODE_SGMII) {
 300                int lane = serdes_get_first_lane(FSL_SRDS_1, SGMII_FM1_DTSEC1
 301                                                 + port);
 302                u8 slot;
 303                if (lane < 0)
 304                        return;
 305                slot = lane_to_slot[lane];
 306                if (slot) {
 307                        /* Slot housing a SGMII riser card */
 308                        sprintf(phy, "phy_s%x_%02x", slot,
 309                                (fm_info_get_phy_address(port - FM1_DTSEC1)-
 310                                CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR + 1));
 311                        fdt_set_phy_handle(fdt, compat, addr, phy);
 312                }
 313        }
 314}
 315
 316void fdt_fixup_board_enet(void *fdt)
 317{
 318        int i, lane, idx;
 319
 320        for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
 321                idx = i - FM1_DTSEC1;
 322                switch (fm_info_get_enet_if(i)) {
 323                case PHY_INTERFACE_MODE_SGMII:
 324                        lane = serdes_get_first_lane(FSL_SRDS_1,
 325                                                     SGMII_FM1_DTSEC1 + idx);
 326                        if (lane < 0)
 327                                break;
 328
 329                        switch (mdio_mux[i]) {
 330                        case EMI1_SLOT3:
 331                                fdt_status_okay_by_alias(fdt, "emi1_slot3");
 332                                break;
 333                        case EMI1_SLOT5:
 334                                fdt_status_okay_by_alias(fdt, "emi1_slot5");
 335                                break;
 336                        case EMI1_SLOT6:
 337                                fdt_status_okay_by_alias(fdt, "emi1_slot6");
 338                                break;
 339                        case EMI1_SLOT7:
 340                                fdt_status_okay_by_alias(fdt, "emi1_slot7");
 341                                break;
 342                        }
 343                break;
 344                case PHY_INTERFACE_MODE_RGMII:
 345                        if (i == FM1_DTSEC4)
 346                                fdt_status_okay_by_alias(fdt, "emi1_rgmii0");
 347
 348                        if (i == FM1_DTSEC5)
 349                                fdt_status_okay_by_alias(fdt, "emi1_rgmii1");
 350                        break;
 351                default:
 352                        break;
 353                }
 354        }
 355}
 356#endif /* #ifdef CONFIG_FMAN_ENET */
 357
 358static void set_brdcfg9_for_gtx_clk(void)
 359{
 360        u8 brdcfg9;
 361        brdcfg9 = QIXIS_READ(brdcfg[9]);
 362/* Initializing EPHY2 clock to RGMII mode */
 363        brdcfg9 &= ~(BRDCFG9_EPHY2_MASK);
 364        brdcfg9 |= (BRDCFG9_EPHY2_VAL);
 365        QIXIS_WRITE(brdcfg[9], brdcfg9);
 366}
 367
 368void t1040_handle_phy_interface_sgmii(int i)
 369{
 370        int lane, idx, slot;
 371        idx = i - FM1_DTSEC1;
 372        lane = serdes_get_first_lane(FSL_SRDS_1,
 373                        SGMII_FM1_DTSEC1 + idx);
 374
 375        if (lane < 0)
 376                return;
 377        slot = lane_to_slot[lane];
 378
 379        switch (slot) {
 380        case 1:
 381                mdio_mux[i] = EMI1_SLOT1;
 382                fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 383                break;
 384        case 3:
 385                if (FM1_DTSEC4 == i)
 386                        fm_info_set_phy_address(i, riser_phy_addr[0]);
 387                if (FM1_DTSEC5 == i)
 388                        fm_info_set_phy_address(i, riser_phy_addr[1]);
 389
 390                mdio_mux[i] = EMI1_SLOT3;
 391
 392                fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 393                break;
 394        case 4:
 395                mdio_mux[i] = EMI1_SLOT4;
 396                fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 397                break;
 398        case 5:
 399                /* Slot housing a SGMII riser card? */
 400                fm_info_set_phy_address(i, riser_phy_addr[0]);
 401                mdio_mux[i] = EMI1_SLOT5;
 402                fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 403                break;
 404        case 6:
 405                /* Slot housing a SGMII riser card? */
 406                fm_info_set_phy_address(i, riser_phy_addr[0]);
 407                mdio_mux[i] = EMI1_SLOT6;
 408                fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 409                break;
 410        case 7:
 411                if (FM1_DTSEC1 == i)
 412                        fm_info_set_phy_address(i, riser_phy_addr[0]);
 413                if (FM1_DTSEC2 == i)
 414                        fm_info_set_phy_address(i, riser_phy_addr[1]);
 415                if (FM1_DTSEC3 == i)
 416                        fm_info_set_phy_address(i, riser_phy_addr[2]);
 417                if (FM1_DTSEC5 == i)
 418                        fm_info_set_phy_address(i, riser_phy_addr[3]);
 419
 420                mdio_mux[i] = EMI1_SLOT7;
 421                fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 422                break;
 423        default:
 424                break;
 425        }
 426        fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 427}
 428void t1040_handle_phy_interface_rgmii(int i)
 429{
 430        fm_info_set_phy_address(i, i == FM1_DTSEC5 ?
 431                        CONFIG_SYS_FM1_DTSEC5_PHY_ADDR :
 432                        CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);
 433        mdio_mux[i] = (i == FM1_DTSEC5) ? EMI1_RGMII1 :
 434                EMI1_RGMII0;
 435        fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 436}
 437
 438int board_eth_init(bd_t *bis)
 439{
 440#ifdef CONFIG_FMAN_ENET
 441        struct memac_mdio_info memac_mdio_info;
 442        unsigned int i;
 443#ifdef CONFIG_VSC9953
 444        int lane;
 445        int phy_addr;
 446        phy_interface_t phy_int;
 447        struct mii_dev *bus;
 448#endif
 449
 450        printf("Initializing Fman\n");
 451        set_brdcfg9_for_gtx_clk();
 452
 453        initialize_lane_to_slot();
 454
 455        /* Initialize the mdio_mux array so we can recognize empty elements */
 456        for (i = 0; i < NUM_FM_PORTS; i++)
 457                mdio_mux[i] = EMI_NONE;
 458
 459        memac_mdio_info.regs =
 460                (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
 461        memac_mdio_info.name = DEFAULT_FM_MDIO_NAME;
 462
 463        /* Register the real 1G MDIO bus */
 464        fm_memac_mdio_init(bis, &memac_mdio_info);
 465
 466        /* Register the muxing front-ends to the MDIO buses */
 467        t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII0);
 468        t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII1);
 469        t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT1);
 470        t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT3);
 471        t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4);
 472        t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT5);
 473        t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT6);
 474        t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT7);
 475
 476        /*
 477         * Program on board RGMII PHY addresses. If the SGMII Riser
 478         * card used, we'll override the PHY address later. For any DTSEC that
 479         * is RGMII, we'll also override its PHY address later. We assume that
 480         * DTSEC4 and DTSEC5 are used for RGMII.
 481         */
 482        fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);
 483        fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_DTSEC5_PHY_ADDR);
 484
 485        for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
 486                switch (fm_info_get_enet_if(i)) {
 487                case PHY_INTERFACE_MODE_QSGMII:
 488                        fm_info_set_mdio(i, NULL);
 489                        break;
 490                case PHY_INTERFACE_MODE_SGMII:
 491                        t1040_handle_phy_interface_sgmii(i);
 492                        break;
 493
 494                case PHY_INTERFACE_MODE_RGMII:
 495                        /* Only DTSEC4 and DTSEC5 can be routed to RGMII */
 496                        t1040_handle_phy_interface_rgmii(i);
 497                        break;
 498                default:
 499                        break;
 500                }
 501        }
 502
 503#ifdef CONFIG_VSC9953
 504        for (i = 0; i < VSC9953_MAX_PORTS; i++) {
 505                lane = -1;
 506                phy_addr = 0;
 507                phy_int = PHY_INTERFACE_MODE_NONE;
 508                switch (i) {
 509                case 0:
 510                case 1:
 511                case 2:
 512                case 3:
 513                        lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_SW1_A);
 514                        /* PHYs connected over QSGMII */
 515                        if (lane >= 0) {
 516                                phy_addr = CONFIG_SYS_FM1_QSGMII21_PHY_ADDR +
 517                                                i;
 518                                phy_int = PHY_INTERFACE_MODE_QSGMII;
 519                                break;
 520                        }
 521                        lane = serdes_get_first_lane(FSL_SRDS_1,
 522                                        SGMII_SW1_MAC1 + i);
 523
 524                        if (lane < 0)
 525                                break;
 526
 527                        /* PHYs connected over QSGMII */
 528                        if (i != 3 || lane_to_slot[lane] == 7)
 529                                phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR
 530                                        + i;
 531                        else
 532                                phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR;
 533                        phy_int = PHY_INTERFACE_MODE_SGMII;
 534                        break;
 535                case 4:
 536                case 5:
 537                case 6:
 538                case 7:
 539                        lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_SW1_B);
 540                        /* PHYs connected over QSGMII */
 541                        if (lane >= 0) {
 542                                phy_addr = CONFIG_SYS_FM1_QSGMII11_PHY_ADDR +
 543                                                i - 4;
 544                                phy_int = PHY_INTERFACE_MODE_QSGMII;
 545                                break;
 546                        }
 547                        lane = serdes_get_first_lane(FSL_SRDS_1,
 548                                        SGMII_SW1_MAC1 + i);
 549                        /* PHYs connected over SGMII */
 550                        if (lane >= 0) {
 551                                phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR
 552                                                + i - 3;
 553                                phy_int = PHY_INTERFACE_MODE_SGMII;
 554                        }
 555                        break;
 556                case 8:
 557                        if (serdes_get_first_lane(FSL_SRDS_1,
 558                                                  SGMII_FM1_DTSEC1) < 0)
 559                                /* FM1@DTSEC1 is connected to SW1@PORT8 */
 560                                vsc9953_port_enable(i);
 561                        break;
 562                case 9:
 563                        if (serdes_get_first_lane(FSL_SRDS_1,
 564                                                  SGMII_FM1_DTSEC2) < 0) {
 565                                /* Enable L2 On MAC2 using SCFG */
 566                                struct ccsr_scfg *scfg = (struct ccsr_scfg *)
 567                                                CONFIG_SYS_MPC85xx_SCFG;
 568
 569                                out_be32(&scfg->esgmiiselcr,
 570                                         in_be32(&scfg->esgmiiselcr) |
 571                                         (0x80000000));
 572                                vsc9953_port_enable(i);
 573                        }
 574                        break;
 575                }
 576
 577                if (lane >= 0) {
 578                        bus = mii_dev_for_muxval(lane_to_slot[lane]);
 579                        vsc9953_port_info_set_mdio(i, bus);
 580                        vsc9953_port_enable(i);
 581                }
 582                vsc9953_port_info_set_phy_address(i, phy_addr);
 583                vsc9953_port_info_set_phy_int(i, phy_int);
 584        }
 585
 586#endif
 587        cpu_eth_init(bis);
 588#endif
 589
 590        return pci_eth_init(bis);
 591}
 592