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