uboot/drivers/net/fm/init.c
<<
>>
Prefs
   1/*
   2 * Copyright 2011-2015 Freescale Semiconductor, Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6#include <errno.h>
   7#include <common.h>
   8#include <asm/io.h>
   9#include <fdt_support.h>
  10#include <fsl_mdio.h>
  11#ifdef CONFIG_FSL_LAYERSCAPE
  12#include <asm/arch/fsl_serdes.h>
  13#else
  14#include <asm/fsl_serdes.h>
  15#endif
  16
  17#include "fm.h"
  18
  19struct fm_eth_info fm_info[] = {
  20#if (CONFIG_SYS_NUM_FM1_DTSEC >= 1)
  21        FM_DTSEC_INFO_INITIALIZER(1, 1),
  22#endif
  23#if (CONFIG_SYS_NUM_FM1_DTSEC >= 2)
  24        FM_DTSEC_INFO_INITIALIZER(1, 2),
  25#endif
  26#if (CONFIG_SYS_NUM_FM1_DTSEC >= 3)
  27        FM_DTSEC_INFO_INITIALIZER(1, 3),
  28#endif
  29#if (CONFIG_SYS_NUM_FM1_DTSEC >= 4)
  30        FM_DTSEC_INFO_INITIALIZER(1, 4),
  31#endif
  32#if (CONFIG_SYS_NUM_FM1_DTSEC >= 5)
  33        FM_DTSEC_INFO_INITIALIZER(1, 5),
  34#endif
  35#if (CONFIG_SYS_NUM_FM1_DTSEC >= 6)
  36        FM_DTSEC_INFO_INITIALIZER(1, 6),
  37#endif
  38#if (CONFIG_SYS_NUM_FM1_DTSEC >= 7)
  39        FM_DTSEC_INFO_INITIALIZER(1, 9),
  40#endif
  41#if (CONFIG_SYS_NUM_FM1_DTSEC >= 8)
  42        FM_DTSEC_INFO_INITIALIZER(1, 10),
  43#endif
  44#if (CONFIG_SYS_NUM_FM2_DTSEC >= 1)
  45        FM_DTSEC_INFO_INITIALIZER(2, 1),
  46#endif
  47#if (CONFIG_SYS_NUM_FM2_DTSEC >= 2)
  48        FM_DTSEC_INFO_INITIALIZER(2, 2),
  49#endif
  50#if (CONFIG_SYS_NUM_FM2_DTSEC >= 3)
  51        FM_DTSEC_INFO_INITIALIZER(2, 3),
  52#endif
  53#if (CONFIG_SYS_NUM_FM2_DTSEC >= 4)
  54        FM_DTSEC_INFO_INITIALIZER(2, 4),
  55#endif
  56#if (CONFIG_SYS_NUM_FM2_DTSEC >= 5)
  57        FM_DTSEC_INFO_INITIALIZER(2, 5),
  58#endif
  59#if (CONFIG_SYS_NUM_FM2_DTSEC >= 6)
  60        FM_DTSEC_INFO_INITIALIZER(2, 6),
  61#endif
  62#if (CONFIG_SYS_NUM_FM2_DTSEC >= 7)
  63        FM_DTSEC_INFO_INITIALIZER(2, 9),
  64#endif
  65#if (CONFIG_SYS_NUM_FM2_DTSEC >= 8)
  66        FM_DTSEC_INFO_INITIALIZER(2, 10),
  67#endif
  68#if (CONFIG_SYS_NUM_FM1_10GEC >= 1)
  69        FM_TGEC_INFO_INITIALIZER(1, 1),
  70#endif
  71#if (CONFIG_SYS_NUM_FM1_10GEC >= 2)
  72        FM_TGEC_INFO_INITIALIZER(1, 2),
  73#endif
  74#if (CONFIG_SYS_NUM_FM1_10GEC >= 3)
  75        FM_TGEC_INFO_INITIALIZER2(1, 3),
  76#endif
  77#if (CONFIG_SYS_NUM_FM1_10GEC >= 4)
  78        FM_TGEC_INFO_INITIALIZER2(1, 4),
  79#endif
  80#if (CONFIG_SYS_NUM_FM2_10GEC >= 1)
  81        FM_TGEC_INFO_INITIALIZER(2, 1),
  82#endif
  83#if (CONFIG_SYS_NUM_FM2_10GEC >= 2)
  84        FM_TGEC_INFO_INITIALIZER(2, 2),
  85#endif
  86};
  87
  88int fm_standard_init(bd_t *bis)
  89{
  90        int i;
  91        struct ccsr_fman *reg;
  92
  93        reg = (void *)CONFIG_SYS_FSL_FM1_ADDR;
  94        if (fm_init_common(0, reg))
  95                return 0;
  96
  97        for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
  98                if ((fm_info[i].enabled) && (fm_info[i].index == 1))
  99                        fm_eth_initialize(reg, &fm_info[i]);
 100        }
 101
 102#if (CONFIG_SYS_NUM_FMAN == 2)
 103        reg = (void *)CONFIG_SYS_FSL_FM2_ADDR;
 104        if (fm_init_common(1, reg))
 105                return 0;
 106
 107        for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
 108                if ((fm_info[i].enabled) && (fm_info[i].index == 2))
 109                        fm_eth_initialize(reg, &fm_info[i]);
 110        }
 111#endif
 112
 113        return 1;
 114}
 115
 116/* simple linear search to map from port to array index */
 117static int fm_port_to_index(enum fm_port port)
 118{
 119        int i;
 120
 121        for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
 122                if (fm_info[i].port == port)
 123                        return i;
 124        }
 125
 126        return -1;
 127}
 128
 129/*
 130 * Determine if an interface is actually active based on HW config
 131 * we expect fman_port_enet_if() to report PHY_INTERFACE_MODE_NONE if
 132 * the interface is not active based on HW cfg of the SoC
 133 */
 134void fman_enet_init(void)
 135{
 136        int i;
 137
 138        for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
 139                phy_interface_t enet_if;
 140
 141                enet_if = fman_port_enet_if(fm_info[i].port);
 142                if (enet_if != PHY_INTERFACE_MODE_NONE) {
 143                        fm_info[i].enabled = 1;
 144                        fm_info[i].enet_if = enet_if;
 145                } else {
 146                        fm_info[i].enabled = 0;
 147                }
 148        }
 149
 150        return ;
 151}
 152
 153void fm_disable_port(enum fm_port port)
 154{
 155        int i = fm_port_to_index(port);
 156
 157        if (i == -1)
 158                return;
 159
 160        fm_info[i].enabled = 0;
 161#ifndef CONFIG_SYS_FMAN_V3
 162        fman_disable_port(port);
 163#endif
 164}
 165
 166void fm_enable_port(enum fm_port port)
 167{
 168        int i = fm_port_to_index(port);
 169
 170        if (i == -1)
 171                return;
 172
 173        fm_info[i].enabled = 1;
 174        fman_enable_port(port);
 175}
 176
 177void fm_info_set_mdio(enum fm_port port, struct mii_dev *bus)
 178{
 179        int i = fm_port_to_index(port);
 180
 181        if (i == -1)
 182                return;
 183
 184        fm_info[i].bus = bus;
 185}
 186
 187void fm_info_set_phy_address(enum fm_port port, int address)
 188{
 189        int i = fm_port_to_index(port);
 190
 191        if (i == -1)
 192                return;
 193
 194        fm_info[i].phy_addr = address;
 195}
 196
 197/*
 198 * Returns the PHY address for a given Fman port
 199 *
 200 * The port must be set via a prior call to fm_info_set_phy_address().
 201 * A negative error code is returned if the port is invalid.
 202 */
 203int fm_info_get_phy_address(enum fm_port port)
 204{
 205        int i = fm_port_to_index(port);
 206
 207        if (i == -1)
 208                return -1;
 209
 210        return fm_info[i].phy_addr;
 211}
 212
 213/*
 214 * Returns the type of the data interface between the given MAC and its PHY.
 215 * This is typically determined by the RCW.
 216 */
 217phy_interface_t fm_info_get_enet_if(enum fm_port port)
 218{
 219        int i = fm_port_to_index(port);
 220
 221        if (i == -1)
 222                return PHY_INTERFACE_MODE_NONE;
 223
 224        if (fm_info[i].enabled)
 225                return fm_info[i].enet_if;
 226
 227        return PHY_INTERFACE_MODE_NONE;
 228}
 229
 230static void
 231__def_board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
 232                                enum fm_port port, int offset)
 233{
 234        return ;
 235}
 236
 237void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
 238                                enum fm_port port, int offset)
 239         __attribute__((weak, alias("__def_board_ft_fman_fixup_port")));
 240
 241int ft_fixup_port(void *blob, struct fm_eth_info *info, char *prop)
 242{
 243        int off;
 244        uint32_t ph;
 245        phys_addr_t paddr = CONFIG_SYS_CCSRBAR_PHYS + info->compat_offset;
 246#ifndef CONFIG_SYS_FMAN_V3
 247        u64 dtsec1_addr = (u64)CONFIG_SYS_CCSRBAR_PHYS +
 248                                CONFIG_SYS_FSL_FM1_DTSEC1_OFFSET;
 249#endif
 250
 251        off = fdt_node_offset_by_compat_reg(blob, prop, paddr);
 252        if (off == -FDT_ERR_NOTFOUND)
 253                return -EINVAL;
 254
 255        if (info->enabled) {
 256                fdt_fixup_phy_connection(blob, off, info->enet_if);
 257                board_ft_fman_fixup_port(blob, prop, paddr, info->port, off);
 258                return 0;
 259        }
 260
 261#ifdef CONFIG_SYS_FMAN_V3
 262#ifndef CONFIG_FSL_FM_10GEC_REGULAR_NOTATION
 263        /*
 264         * On T2/T4 SoCs, physically FM1_DTSEC9 and FM1_10GEC1 use the same
 265         * dual-role MAC, when FM1_10GEC1 is enabled and  FM1_DTSEC9
 266         * is disabled, ensure that the dual-role MAC is not disabled,
 267         * ditto for other dual-role MACs.
 268         */
 269        if (((info->port == FM1_DTSEC9) && (PORT_IS_ENABLED(FM1_10GEC1)))  ||
 270            ((info->port == FM1_DTSEC10) && (PORT_IS_ENABLED(FM1_10GEC2))) ||
 271            ((info->port == FM1_DTSEC1) && (PORT_IS_ENABLED(FM1_10GEC3)))  ||
 272            ((info->port == FM1_DTSEC2) && (PORT_IS_ENABLED(FM1_10GEC4)))  ||
 273            ((info->port == FM1_10GEC1) && (PORT_IS_ENABLED(FM1_DTSEC9)))  ||
 274            ((info->port == FM1_10GEC2) && (PORT_IS_ENABLED(FM1_DTSEC10))) ||
 275            ((info->port == FM1_10GEC3) && (PORT_IS_ENABLED(FM1_DTSEC1)))  ||
 276            ((info->port == FM1_10GEC4) && (PORT_IS_ENABLED(FM1_DTSEC2)))
 277#if (CONFIG_SYS_NUM_FMAN == 2)
 278                                                                                ||
 279            ((info->port == FM2_DTSEC9) && (PORT_IS_ENABLED(FM2_10GEC1)))       ||
 280            ((info->port == FM2_DTSEC10) && (PORT_IS_ENABLED(FM2_10GEC2)))      ||
 281            ((info->port == FM2_10GEC1) && (PORT_IS_ENABLED(FM2_DTSEC9)))       ||
 282            ((info->port == FM2_10GEC2) && (PORT_IS_ENABLED(FM2_DTSEC10)))
 283#endif
 284#else
 285        /* FM1_DTSECx and FM1_10GECx use the same dual-role MAC */
 286        if (((info->port == FM1_DTSEC1) && (PORT_IS_ENABLED(FM1_10GEC1)))  ||
 287            ((info->port == FM1_DTSEC2) && (PORT_IS_ENABLED(FM1_10GEC2)))  ||
 288            ((info->port == FM1_DTSEC3) && (PORT_IS_ENABLED(FM1_10GEC3)))  ||
 289            ((info->port == FM1_DTSEC4) && (PORT_IS_ENABLED(FM1_10GEC4)))  ||
 290            ((info->port == FM1_10GEC1) && (PORT_IS_ENABLED(FM1_DTSEC1)))  ||
 291            ((info->port == FM1_10GEC2) && (PORT_IS_ENABLED(FM1_DTSEC2)))  ||
 292            ((info->port == FM1_10GEC3) && (PORT_IS_ENABLED(FM1_DTSEC3)))  ||
 293            ((info->port == FM1_10GEC4) && (PORT_IS_ENABLED(FM1_DTSEC4)))
 294#endif
 295        )
 296                return 0;
 297#endif
 298        /* board code might have caused offset to change */
 299        off = fdt_node_offset_by_compat_reg(blob, prop, paddr);
 300
 301#ifndef CONFIG_SYS_FMAN_V3
 302        /* Don't disable FM1-DTSEC1 MAC as its used for MDIO */
 303        if (paddr != dtsec1_addr)
 304#endif
 305                fdt_status_disabled(blob, off); /* disable the MAC node */
 306
 307        /* disable the fsl,dpa-ethernet node that points to the MAC */
 308        ph = fdt_get_phandle(blob, off);
 309        do_fixup_by_prop(blob, "fsl,fman-mac", &ph, sizeof(ph),
 310                "status", "disabled", strlen("disabled") + 1, 1);
 311
 312        return 0;
 313}
 314
 315void fdt_fixup_fman_ethernet(void *blob)
 316{
 317        int i;
 318
 319#ifdef CONFIG_SYS_FMAN_V3
 320        for (i = 0; i < ARRAY_SIZE(fm_info); i++)
 321                ft_fixup_port(blob, &fm_info[i], "fsl,fman-memac");
 322#else
 323        for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
 324                /* Try the new compatible first.
 325                 * If the node is missing, try the old.
 326                 */
 327                if (fm_info[i].type == FM_ETH_1G_E) {
 328                        if (ft_fixup_port(blob, &fm_info[i], "fsl,fman-dtsec"))
 329                                ft_fixup_port(blob, &fm_info[i],
 330                                              "fsl,fman-1g-mac");
 331                } else {
 332                        if (ft_fixup_port(blob, &fm_info[i], "fsl,fman-tgec"))
 333                                ft_fixup_port(blob, &fm_info[i],
 334                                              "fsl,fman-10g-mac");
 335                }
 336        }
 337#endif
 338}
 339
 340/*QSGMII Riser Card can work in SGMII mode, but the PHY address is different.
 341 *This function scans which Riser Card being used(QSGMII or SGMII Riser Card),
 342 *then set the correct PHY address
 343 */
 344void set_sgmii_phy(struct mii_dev *bus, enum fm_port base_port,
 345                unsigned int port_num, int phy_base_addr)
 346{
 347        unsigned int regnum = 0;
 348        int qsgmii;
 349        int i;
 350        int phy_real_addr;
 351
 352        qsgmii = is_qsgmii_riser_card(bus, phy_base_addr, port_num, regnum);
 353
 354        if (!qsgmii)
 355                return;
 356
 357        for (i = base_port; i < base_port + port_num; i++) {
 358                if (fm_info_get_enet_if(i) == PHY_INTERFACE_MODE_SGMII) {
 359                        phy_real_addr = phy_base_addr + i - base_port;
 360                        fm_info_set_phy_address(i, phy_real_addr);
 361                }
 362        }
 363}
 364
 365/*to check whether qsgmii riser card is used*/
 366int is_qsgmii_riser_card(struct mii_dev *bus, int phy_base_addr,
 367                unsigned int port_num, unsigned regnum)
 368{
 369        int i;
 370        int val;
 371
 372        if (!bus)
 373                return 0;
 374
 375        for (i = phy_base_addr; i < phy_base_addr + port_num; i++) {
 376                val = bus->read(bus, i, MDIO_DEVAD_NONE, regnum);
 377                if (val != MIIM_TIMEOUT)
 378                        return 1;
 379        }
 380
 381        return 0;
 382}
 383