uboot/board/freescale/ls1046aqds/eth.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2016 Freescale Semiconductor, Inc.
   4 * Copyright 2018-2020 NXP
   5 */
   6
   7#include <common.h>
   8#include <log.h>
   9#include <net.h>
  10#include <asm/io.h>
  11#include <netdev.h>
  12#include <fdt_support.h>
  13#include <fm_eth.h>
  14#include <fsl_mdio.h>
  15#include <fsl_dtsec.h>
  16#include <malloc.h>
  17#include <asm/arch/fsl_serdes.h>
  18
  19#include "../common/qixis.h"
  20#include "../common/fman.h"
  21#include "ls1046aqds_qixis.h"
  22
  23#define EMI_NONE        0xFF
  24#define EMI1_RGMII1     0
  25#define EMI1_RGMII2     1
  26#define EMI1_SLOT1      2
  27#define EMI1_SLOT2      3
  28#define EMI1_SLOT4      4
  29
  30static int mdio_mux[NUM_FM_PORTS];
  31
  32static const char * const mdio_names[] = {
  33        "LS1046AQDS_MDIO_RGMII1",
  34        "LS1046AQDS_MDIO_RGMII2",
  35        "LS1046AQDS_MDIO_SLOT1",
  36        "LS1046AQDS_MDIO_SLOT2",
  37        "LS1046AQDS_MDIO_SLOT4",
  38        "NULL",
  39};
  40
  41/* Map SerDes 1 & 2 lanes to default slot. */
  42static u8 lane_to_slot[] = {1, 1, 1, 1, 0, 4, 0 , 0};
  43
  44static const char *ls1046aqds_mdio_name_for_muxval(u8 muxval)
  45{
  46        return mdio_names[muxval];
  47}
  48
  49struct mii_dev *mii_dev_for_muxval(u8 muxval)
  50{
  51        struct mii_dev *bus;
  52        const char *name;
  53
  54        if (muxval > EMI1_SLOT4)
  55                return NULL;
  56
  57        name = ls1046aqds_mdio_name_for_muxval(muxval);
  58
  59        if (!name) {
  60                printf("No bus for muxval %x\n", muxval);
  61                return NULL;
  62        }
  63
  64        bus = miiphy_get_dev_by_name(name);
  65
  66        if (!bus) {
  67                printf("No bus by name %s\n", name);
  68                return NULL;
  69        }
  70
  71        return bus;
  72}
  73
  74struct ls1046aqds_mdio {
  75        u8 muxval;
  76        struct mii_dev *realbus;
  77};
  78
  79static void ls1046aqds_mux_mdio(u8 muxval)
  80{
  81        u8 brdcfg4;
  82
  83        if (muxval < 7) {
  84                brdcfg4 = QIXIS_READ(brdcfg[4]);
  85                brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
  86                brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT);
  87                QIXIS_WRITE(brdcfg[4], brdcfg4);
  88        }
  89}
  90
  91static int ls1046aqds_mdio_read(struct mii_dev *bus, int addr, int devad,
  92                              int regnum)
  93{
  94        struct ls1046aqds_mdio *priv = bus->priv;
  95
  96        ls1046aqds_mux_mdio(priv->muxval);
  97
  98        return priv->realbus->read(priv->realbus, addr, devad, regnum);
  99}
 100
 101static int ls1046aqds_mdio_write(struct mii_dev *bus, int addr, int devad,
 102                               int regnum, u16 value)
 103{
 104        struct ls1046aqds_mdio *priv = bus->priv;
 105
 106        ls1046aqds_mux_mdio(priv->muxval);
 107
 108        return priv->realbus->write(priv->realbus, addr, devad,
 109                                    regnum, value);
 110}
 111
 112static int ls1046aqds_mdio_reset(struct mii_dev *bus)
 113{
 114        struct ls1046aqds_mdio *priv = bus->priv;
 115
 116        return priv->realbus->reset(priv->realbus);
 117}
 118
 119static int ls1046aqds_mdio_init(char *realbusname, u8 muxval)
 120{
 121        struct ls1046aqds_mdio *pmdio;
 122        struct mii_dev *bus = mdio_alloc();
 123
 124        if (!bus) {
 125                printf("Failed to allocate ls1046aqds MDIO bus\n");
 126                return -1;
 127        }
 128
 129        pmdio = malloc(sizeof(*pmdio));
 130        if (!pmdio) {
 131                printf("Failed to allocate ls1046aqds private data\n");
 132                free(bus);
 133                return -1;
 134        }
 135
 136        bus->read = ls1046aqds_mdio_read;
 137        bus->write = ls1046aqds_mdio_write;
 138        bus->reset = ls1046aqds_mdio_reset;
 139        sprintf(bus->name, ls1046aqds_mdio_name_for_muxval(muxval));
 140
 141        pmdio->realbus = miiphy_get_dev_by_name(realbusname);
 142
 143        if (!pmdio->realbus) {
 144                printf("No bus with name %s\n", realbusname);
 145                free(bus);
 146                free(pmdio);
 147                return -1;
 148        }
 149
 150        pmdio->muxval = muxval;
 151        bus->priv = pmdio;
 152        return mdio_register(bus);
 153}
 154
 155void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
 156                              enum fm_port port, int offset)
 157{
 158        struct fixed_link f_link;
 159        const char *phyconn;
 160
 161        if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) {
 162                switch (port) {
 163                case FM1_DTSEC9:
 164                        fdt_set_phy_handle(fdt, compat, addr, "sgmii-s1-p1");
 165                        break;
 166                case FM1_DTSEC10:
 167                        fdt_set_phy_handle(fdt, compat, addr, "sgmii-s1-p2");
 168                        break;
 169                case FM1_DTSEC5:
 170                        fdt_set_phy_handle(fdt, compat, addr, "sgmii-s1-p3");
 171                        break;
 172                case FM1_DTSEC6:
 173                        fdt_set_phy_handle(fdt, compat, addr, "sgmii-s1-p4");
 174                        break;
 175                case FM1_DTSEC2:
 176                        fdt_set_phy_handle(fdt, compat, addr, "sgmii-s4-p1");
 177                        break;
 178                default:
 179                        break;
 180                }
 181        } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII_2500) {
 182                /* 2.5G SGMII interface */
 183                f_link.phy_id = cpu_to_fdt32(port);
 184                f_link.duplex = cpu_to_fdt32(1);
 185                f_link.link_speed = cpu_to_fdt32(1000);
 186                f_link.pause = 0;
 187                f_link.asym_pause = 0;
 188                /* no PHY for 2.5G SGMII on QDS */
 189                fdt_delprop(fdt, offset, "phy-handle");
 190                fdt_setprop(fdt, offset, "fixed-link", &f_link, sizeof(f_link));
 191                fdt_setprop_string(fdt, offset, "phy-connection-type",
 192                                   "sgmii-2500");
 193        } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_QSGMII) {
 194                switch (port) {
 195                case FM1_DTSEC1:
 196                        fdt_set_phy_handle(fdt, compat, addr, "qsgmii-s2-p4");
 197                        break;
 198                case FM1_DTSEC5:
 199                        fdt_set_phy_handle(fdt, compat, addr, "qsgmii-s2-p2");
 200                        break;
 201                case FM1_DTSEC6:
 202                        fdt_set_phy_handle(fdt, compat, addr, "qsgmii-s2-p1");
 203                        break;
 204                case FM1_DTSEC10:
 205                        fdt_set_phy_handle(fdt, compat, addr, "qsgmii-s2-p3");
 206                        break;
 207                default:
 208                        break;
 209                }
 210                fdt_delprop(fdt, offset, "phy-connection-type");
 211                fdt_setprop_string(fdt, offset, "phy-connection-type",
 212                                   "qsgmii");
 213        } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_XGMII &&
 214                   (port == FM1_10GEC1 || port == FM1_10GEC2)) {
 215                phyconn = fdt_getprop(fdt, offset, "phy-connection-type", NULL);
 216                if (is_backplane_mode(phyconn)) {
 217                        /* Backplane KR mode: skip fixups */
 218                        printf("Interface %d in backplane KR mode\n", port);
 219                } else {
 220                        /* XFI interface */
 221                        f_link.phy_id = cpu_to_fdt32(port);
 222                        f_link.duplex = cpu_to_fdt32(1);
 223                        f_link.link_speed = cpu_to_fdt32(10000);
 224                        f_link.pause = 0;
 225                        f_link.asym_pause = 0;
 226                        /* no PHY for XFI */
 227                        fdt_delprop(fdt, offset, "phy-handle");
 228                        fdt_setprop(fdt, offset, "fixed-link", &f_link,
 229                                    sizeof(f_link));
 230                        fdt_setprop_string(fdt, offset, "phy-connection-type",
 231                                           "xgmii");
 232                }
 233        }
 234}
 235
 236void fdt_fixup_board_enet(void *fdt)
 237{
 238        int i;
 239
 240        for (i = FM1_DTSEC1; i < NUM_FM_PORTS; i++) {
 241                switch (fm_info_get_enet_if(i)) {
 242                case PHY_INTERFACE_MODE_SGMII:
 243                case PHY_INTERFACE_MODE_QSGMII:
 244                        switch (mdio_mux[i]) {
 245                        case EMI1_SLOT1:
 246                                fdt_status_okay_by_alias(fdt, "emi1-slot1");
 247                                break;
 248                        case EMI1_SLOT2:
 249                                fdt_status_okay_by_alias(fdt, "emi1-slot2");
 250                                break;
 251                        case EMI1_SLOT4:
 252                                fdt_status_okay_by_alias(fdt, "emi1-slot4");
 253                                break;
 254                        default:
 255                                break;
 256                        }
 257                        break;
 258                default:
 259                        break;
 260                }
 261        }
 262}
 263
 264int board_eth_init(struct bd_info *bis)
 265{
 266#ifdef CONFIG_FMAN_ENET
 267        int i, idx, lane, slot, interface;
 268        struct memac_mdio_info dtsec_mdio_info;
 269        struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
 270        u32 srds_s1, srds_s2;
 271        u8 brdcfg12;
 272
 273        srds_s1 = in_be32(&gur->rcwsr[4]) &
 274                        FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
 275        srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
 276
 277        srds_s2 = in_be32(&gur->rcwsr[4]) &
 278                        FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
 279        srds_s2 >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
 280
 281        /* Initialize the mdio_mux array so we can recognize empty elements */
 282        for (i = 0; i < NUM_FM_PORTS; i++)
 283                mdio_mux[i] = EMI_NONE;
 284
 285        dtsec_mdio_info.regs =
 286                (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
 287
 288        dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
 289
 290        /* Register the 1G MDIO bus */
 291        fm_memac_mdio_init(bis, &dtsec_mdio_info);
 292
 293        /* Register the muxing front-ends to the MDIO buses */
 294        ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII1);
 295        ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII2);
 296        ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT1);
 297        ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT2);
 298        ls1046aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4);
 299
 300        /* Set the two on-board RGMII PHY address */
 301        fm_info_set_phy_address(FM1_DTSEC3, RGMII_PHY1_ADDR);
 302        fm_info_set_phy_address(FM1_DTSEC4, RGMII_PHY2_ADDR);
 303
 304        switch (srds_s1) {
 305        case 0x3333:
 306                /* SGMII on slot 1, MAC 9 */
 307                fm_info_set_phy_address(FM1_DTSEC9, SGMII_CARD_PORT1_PHY_ADDR);
 308        case 0x1333:
 309        case 0x2333:
 310                /* SGMII on slot 1, MAC 10 */
 311                fm_info_set_phy_address(FM1_DTSEC10, SGMII_CARD_PORT2_PHY_ADDR);
 312        case 0x1133:
 313        case 0x2233:
 314                /* SGMII on slot 1, MAC 5/6 */
 315                fm_info_set_phy_address(FM1_DTSEC5, SGMII_CARD_PORT3_PHY_ADDR);
 316                fm_info_set_phy_address(FM1_DTSEC6, SGMII_CARD_PORT4_PHY_ADDR);
 317                break;
 318        case 0x1040:
 319        case 0x2040:
 320                /* QSGMII on lane B, MAC 6/5/10/1 */
 321                fm_info_set_phy_address(FM1_DTSEC6,
 322                                        QSGMII_CARD_PORT1_PHY_ADDR_S2);
 323                fm_info_set_phy_address(FM1_DTSEC5,
 324                                        QSGMII_CARD_PORT2_PHY_ADDR_S2);
 325                fm_info_set_phy_address(FM1_DTSEC10,
 326                                        QSGMII_CARD_PORT3_PHY_ADDR_S2);
 327                fm_info_set_phy_address(FM1_DTSEC1,
 328                                        QSGMII_CARD_PORT4_PHY_ADDR_S2);
 329                break;
 330        case 0x3363:
 331                /* SGMII on slot 1, MAC 9/10 */
 332                fm_info_set_phy_address(FM1_DTSEC9, SGMII_CARD_PORT1_PHY_ADDR);
 333                fm_info_set_phy_address(FM1_DTSEC10, SGMII_CARD_PORT2_PHY_ADDR);
 334        case 0x1163:
 335        case 0x2263:
 336        case 0x2223:
 337                /* SGMII on slot 1, MAC 6 */
 338                fm_info_set_phy_address(FM1_DTSEC6, SGMII_CARD_PORT4_PHY_ADDR);
 339                break;
 340        default:
 341                printf("Invalid SerDes protocol 0x%x for LS1046AQDS\n",
 342                       srds_s1);
 343                break;
 344        }
 345
 346        if (srds_s2 == 0x5a59 || srds_s2 == 0x5a06)
 347                /* SGMII on slot 4, MAC 2 */
 348                fm_info_set_phy_address(FM1_DTSEC2, SGMII_CARD_PORT1_PHY_ADDR);
 349
 350        for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
 351                idx = i - FM1_DTSEC1;
 352                interface = fm_info_get_enet_if(i);
 353                switch (interface) {
 354                case PHY_INTERFACE_MODE_SGMII:
 355                case PHY_INTERFACE_MODE_QSGMII:
 356                        if (interface == PHY_INTERFACE_MODE_SGMII) {
 357                                if (i == FM1_DTSEC5) {
 358                                        /* route lane 2 to slot1 so to have
 359                                         * one sgmii riser card supports
 360                                         * MAC5 and MAC6.
 361                                         */
 362                                        brdcfg12 = QIXIS_READ(brdcfg[12]);
 363                                        QIXIS_WRITE(brdcfg[12],
 364                                                    brdcfg12 | 0x80);
 365                                }
 366                                lane = serdes_get_first_lane(FSL_SRDS_1,
 367                                                SGMII_FM1_DTSEC1 + idx);
 368                        } else {
 369                                /* clear the bit 7 to route lane B on slot2. */
 370                                brdcfg12 = QIXIS_READ(brdcfg[12]);
 371                                QIXIS_WRITE(brdcfg[12], brdcfg12 & 0x7f);
 372
 373                                lane = serdes_get_first_lane(FSL_SRDS_1,
 374                                                QSGMII_FM1_A);
 375                                lane_to_slot[lane] = 2;
 376                        }
 377
 378                        if (i == FM1_DTSEC2)
 379                                lane = 5;
 380
 381                        if (lane < 0)
 382                                break;
 383
 384                        slot = lane_to_slot[lane];
 385                        debug("FM1@DTSEC%u expects SGMII in slot %u\n",
 386                              idx + 1, slot);
 387                        if (QIXIS_READ(present2) & (1 << (slot - 1)))
 388                                fm_disable_port(i);
 389
 390                        switch (slot) {
 391                        case 1:
 392                                mdio_mux[i] = EMI1_SLOT1;
 393                                fm_info_set_mdio(i, mii_dev_for_muxval(
 394                                                 mdio_mux[i]));
 395                                break;
 396                        case 2:
 397                                mdio_mux[i] = EMI1_SLOT2;
 398                                fm_info_set_mdio(i, mii_dev_for_muxval(
 399                                                 mdio_mux[i]));
 400                                break;
 401                        case 4:
 402                                mdio_mux[i] = EMI1_SLOT4;
 403                                fm_info_set_mdio(i, mii_dev_for_muxval(
 404                                                 mdio_mux[i]));
 405                                break;
 406                        default:
 407                                break;
 408                        }
 409                        break;
 410                case PHY_INTERFACE_MODE_RGMII:
 411                case PHY_INTERFACE_MODE_RGMII_TXID:
 412                case PHY_INTERFACE_MODE_RGMII_RXID:
 413                case PHY_INTERFACE_MODE_RGMII_ID:
 414                        if (i == FM1_DTSEC3)
 415                                mdio_mux[i] = EMI1_RGMII1;
 416                        else if (i == FM1_DTSEC4)
 417                                mdio_mux[i] = EMI1_RGMII2;
 418                        fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
 419                        break;
 420                default:
 421                        break;
 422                }
 423        }
 424
 425        cpu_eth_init(bis);
 426#endif /* CONFIG_FMAN_ENET */
 427
 428        return pci_eth_init(bis);
 429}
 430