uboot/drivers/net/fm/memac_phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2012 Freescale Semiconductor, Inc.
   4 *      Andy Fleming <afleming@gmail.com>
   5 *      Roy Zang <tie-fei.zang@freescale.com>
   6 * Some part is taken from tsec.c
   7 */
   8#include <common.h>
   9#include <miiphy.h>
  10#include <phy.h>
  11#include <asm/io.h>
  12#include <fsl_memac.h>
  13#include <fm_eth.h>
  14
  15#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
  16#define memac_out_32(a, v)      out_le32(a, v)
  17#define memac_clrbits_32(a, v)  clrbits_le32(a, v)
  18#define memac_setbits_32(a, v)  setbits_le32(a, v)
  19#else
  20#define memac_out_32(a, v)      out_be32(a, v)
  21#define memac_clrbits_32(a, v)  clrbits_be32(a, v)
  22#define memac_setbits_32(a, v)  setbits_be32(a, v)
  23#endif
  24
  25static u32 memac_in_32(u32 *reg)
  26{
  27#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
  28        return in_le32(reg);
  29#else
  30        return in_be32(reg);
  31#endif
  32}
  33
  34/*
  35 * Write value to the PHY for this device to the register at regnum, waiting
  36 * until the write is done before it returns.  All PHY configuration has to be
  37 * done through the TSEC1 MIIM regs
  38 */
  39int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
  40                        int regnum, u16 value)
  41{
  42        u32 mdio_ctl;
  43        struct memac_mdio_controller *regs = bus->priv;
  44        u32 c45 = 1; /* Default to 10G interface */
  45
  46        if (dev_addr == MDIO_DEVAD_NONE) {
  47                c45 = 0; /* clause 22 */
  48                dev_addr = regnum & 0x1f;
  49                memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
  50        } else
  51                memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
  52
  53        /* Wait till the bus is free */
  54        while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  55                ;
  56
  57        /* Set the port and dev addr */
  58        mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
  59        memac_out_32(&regs->mdio_ctl, mdio_ctl);
  60
  61        /* Set the register address */
  62        if (c45)
  63                memac_out_32(&regs->mdio_addr, regnum & 0xffff);
  64
  65        /* Wait till the bus is free */
  66        while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  67                ;
  68
  69        /* Write the value to the register */
  70        memac_out_32(&regs->mdio_data, MDIO_DATA(value));
  71
  72        /* Wait till the MDIO write is complete */
  73        while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
  74                ;
  75
  76        return 0;
  77}
  78
  79/*
  80 * Reads from register regnum in the PHY for device dev, returning the value.
  81 * Clears miimcom first.  All PHY configuration has to be done through the
  82 * TSEC1 MIIM regs
  83 */
  84int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
  85                        int regnum)
  86{
  87        u32 mdio_ctl;
  88        struct memac_mdio_controller *regs = bus->priv;
  89        u32 c45 = 1;
  90
  91        if (dev_addr == MDIO_DEVAD_NONE) {
  92                if (!strcmp(bus->name, DEFAULT_FM_TGEC_MDIO_NAME))
  93                        return 0xffff;
  94                c45 = 0; /* clause 22 */
  95                dev_addr = regnum & 0x1f;
  96                memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
  97        } else
  98                memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
  99
 100        /* Wait till the bus is free */
 101        while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
 102                ;
 103
 104        /* Set the Port and Device Addrs */
 105        mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
 106        memac_out_32(&regs->mdio_ctl, mdio_ctl);
 107
 108        /* Set the register address */
 109        if (c45)
 110                memac_out_32(&regs->mdio_addr, regnum & 0xffff);
 111
 112        /* Wait till the bus is free */
 113        while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
 114                ;
 115
 116        /* Initiate the read */
 117        mdio_ctl |= MDIO_CTL_READ;
 118        memac_out_32(&regs->mdio_ctl, mdio_ctl);
 119
 120        /* Wait till the MDIO write is complete */
 121        while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
 122                ;
 123
 124        /* Return all Fs if nothing was there */
 125        if (memac_in_32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
 126                return 0xffff;
 127
 128        return memac_in_32(&regs->mdio_data) & 0xffff;
 129}
 130
 131int memac_mdio_reset(struct mii_dev *bus)
 132{
 133        return 0;
 134}
 135
 136int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
 137{
 138        struct mii_dev *bus = mdio_alloc();
 139
 140        if (!bus) {
 141                printf("Failed to allocate FM TGEC MDIO bus\n");
 142                return -1;
 143        }
 144
 145        bus->read = memac_mdio_read;
 146        bus->write = memac_mdio_write;
 147        bus->reset = memac_mdio_reset;
 148        strcpy(bus->name, info->name);
 149
 150        bus->priv = info->regs;
 151
 152        /*
 153         * On some platforms like B4860, default value of MDIO_CLK_DIV bits
 154         * in mdio_stat(mdio_cfg) register generates MDIO clock too high
 155         * (much higher than 2.5MHz), violating the IEEE specs.
 156         * On other platforms like T1040, default value of MDIO_CLK_DIV bits
 157         * is zero, so MDIO clock is disabled.
 158         * So, for proper functioning of MDIO, MDIO_CLK_DIV bits needs to
 159         * be properly initialized.
 160         * NEG bit default should be '1' as per FMAN-v3 RM, but on platform
 161         * like T2080QDS, this bit default is '0', which leads to MDIO failure
 162         * on XAUI PHY, so set this bit definitely.
 163         */
 164        memac_setbits_32(
 165                &((struct memac_mdio_controller *)info->regs)->mdio_stat,
 166                MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
 167
 168        return mdio_register(bus);
 169}
 170