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