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