uboot/board/freescale/ls1021aqds/eth.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2014 Freescale Semiconductor, Inc.
   4 *
   5 * This file handles the board muxing between the RGMII/SGMII PHYs on
   6 * Freescale LS1021AQDS board. The RGMII PHYs are the three on-board 1Gb
   7 * ports. The SGMII PHYs are provided by the standard Freescale four-port
   8 * SGMII riser card.
   9 *
  10 * Muxing is handled via the PIXIS BRDCFG4 register. The EMI1 bits control
  11 * muxing among the RGMII PHYs and the SGMII PHYs. The value for RGMII depends
  12 * on which port is used. The value for SGMII depends on which slot the riser
  13 * is inserted in.
  14 */
  15
  16#include <common.h>
  17#include <netdev.h>
  18#include <asm/arch/fsl_serdes.h>
  19#include <fsl_mdio.h>
  20#include <tsec.h>
  21#include <malloc.h>
  22
  23#include "../common/sgmii_riser.h"
  24#include "../common/qixis.h"
  25
  26#define EMI1_MASK       0x1f
  27#define EMI1_RGMII0     1
  28#define EMI1_RGMII1     2
  29#define EMI1_RGMII2     3
  30#define EMI1_SGMII1     0x1c
  31#define EMI1_SGMII2     0x1d
  32
  33struct ls1021a_mdio {
  34        struct mii_dev *realbus;
  35};
  36
  37static void ls1021a_mux_mdio(int addr)
  38{
  39        u8 brdcfg4;
  40
  41        brdcfg4 = QIXIS_READ(brdcfg[4]);
  42        brdcfg4 &= EMI1_MASK;
  43
  44        switch (addr) {
  45        case EMI1_RGMII0:
  46                brdcfg4 |= 0;
  47                break;
  48        case EMI1_RGMII1:
  49                brdcfg4 |= 0x20;
  50                break;
  51        case EMI1_RGMII2:
  52                brdcfg4 |= 0x40;
  53                break;
  54        case EMI1_SGMII1:
  55                brdcfg4 |= 0x60;
  56                break;
  57        case EMI1_SGMII2:
  58                brdcfg4 |= 0x80;
  59                break;
  60        default:
  61                brdcfg4 |= 0xa0;
  62                break;
  63        }
  64
  65        QIXIS_WRITE(brdcfg[4], brdcfg4);
  66}
  67
  68static int ls1021a_mdio_read(struct mii_dev *bus, int addr, int devad,
  69                             int regnum)
  70{
  71        struct ls1021a_mdio *priv = bus->priv;
  72
  73        ls1021a_mux_mdio(addr);
  74
  75        return priv->realbus->read(priv->realbus, addr, devad, regnum);
  76}
  77
  78static int ls1021a_mdio_write(struct mii_dev *bus, int addr, int devad,
  79                              int regnum, u16 value)
  80{
  81        struct ls1021a_mdio *priv = bus->priv;
  82
  83        ls1021a_mux_mdio(addr);
  84
  85        return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
  86}
  87
  88static int ls1021a_mdio_reset(struct mii_dev *bus)
  89{
  90        struct ls1021a_mdio *priv = bus->priv;
  91
  92        return priv->realbus->reset(priv->realbus);
  93}
  94
  95static int ls1021a_mdio_init(char *realbusname, char *fakebusname)
  96{
  97        struct ls1021a_mdio *lsmdio;
  98        struct mii_dev *bus = mdio_alloc();
  99
 100        if (!bus) {
 101                printf("Failed to allocate LS102xA MDIO bus\n");
 102                return -1;
 103        }
 104
 105        lsmdio = malloc(sizeof(*lsmdio));
 106        if (!lsmdio) {
 107                printf("Failed to allocate LS102xA private data\n");
 108                free(bus);
 109                return -1;
 110        }
 111
 112        bus->read = ls1021a_mdio_read;
 113        bus->write = ls1021a_mdio_write;
 114        bus->reset = ls1021a_mdio_reset;
 115        strcpy(bus->name, fakebusname);
 116
 117        lsmdio->realbus = miiphy_get_dev_by_name(realbusname);
 118
 119        if (!lsmdio->realbus) {
 120                printf("No bus with name %s\n", realbusname);
 121                free(bus);
 122                free(lsmdio);
 123                return -1;
 124        }
 125
 126        bus->priv = lsmdio;
 127
 128        return mdio_register(bus);
 129}
 130
 131int board_eth_init(bd_t *bis)
 132{
 133        struct fsl_pq_mdio_info mdio_info;
 134        struct tsec_info_struct tsec_info[3];
 135        int num = 0;
 136
 137#ifdef CONFIG_TSEC1
 138        SET_STD_TSEC_INFO(tsec_info[num], 1);
 139        if (is_serdes_configured(SGMII_TSEC1)) {
 140                puts("eTSEC1 is in sgmii mode\n");
 141                tsec_info[num].flags |= TSEC_SGMII;
 142                tsec_info[num].mii_devname = "LS1021A_SGMII_MDIO";
 143        } else {
 144                tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
 145        }
 146        num++;
 147#endif
 148#ifdef CONFIG_TSEC2
 149        SET_STD_TSEC_INFO(tsec_info[num], 2);
 150        if (is_serdes_configured(SGMII_TSEC2)) {
 151                puts("eTSEC2 is in sgmii mode\n");
 152                tsec_info[num].flags |= TSEC_SGMII;
 153                tsec_info[num].mii_devname = "LS1021A_SGMII_MDIO";
 154        } else {
 155                tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
 156        }
 157        num++;
 158#endif
 159#ifdef CONFIG_TSEC3
 160        SET_STD_TSEC_INFO(tsec_info[num], 3);
 161        tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
 162        num++;
 163#endif
 164        if (!num) {
 165                printf("No TSECs initialized\n");
 166                return 0;
 167        }
 168
 169#ifdef CONFIG_FSL_SGMII_RISER
 170        fsl_sgmii_riser_init(tsec_info, num);
 171#endif
 172
 173        mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
 174        mdio_info.name = DEFAULT_MII_NAME;
 175
 176        fsl_pq_mdio_init(bis, &mdio_info);
 177
 178        /* Register the virtual MDIO front-ends */
 179        ls1021a_mdio_init(DEFAULT_MII_NAME, "LS1021A_RGMII_MDIO");
 180        ls1021a_mdio_init(DEFAULT_MII_NAME, "LS1021A_SGMII_MDIO");
 181
 182        tsec_eth_init(bis, tsec_info, num);
 183
 184        return pci_eth_init(bis);
 185}
 186