uboot/drivers/net/fm/tgec_phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2009-2011 Freescale Semiconductor, Inc.
   4 *      Andy Fleming <afleming@gmail.com>
   5 * Some part is taken from tsec.c
   6 */
   7#include <common.h>
   8#include <miiphy.h>
   9#include <phy.h>
  10#include <asm/io.h>
  11#include <fsl_tgec.h>
  12#include <fm_eth.h>
  13
  14/*
  15 * Write value to the PHY for this device to the register at regnum, waiting
  16 * until the write is done before it returns.  All PHY configuration has to be
  17 * done through the TSEC1 MIIM regs
  18 */
  19static int tgec_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
  20                           int regnum, u16 value)
  21{
  22        u32 mdio_ctl;
  23        u32 stat_val;
  24        struct tgec_mdio_controller *regs = bus->priv;
  25
  26        if (dev_addr == MDIO_DEVAD_NONE)
  27                return 0;
  28
  29        /* Wait till the bus is free */
  30        stat_val = MDIO_STAT_CLKDIV(100);
  31        out_be32(&regs->mdio_stat, stat_val);
  32        while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  33                ;
  34
  35        /* Set the port and dev addr */
  36        mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
  37        out_be32(&regs->mdio_ctl, mdio_ctl);
  38
  39        /* Set the register address */
  40        out_be32(&regs->mdio_addr, regnum & 0xffff);
  41
  42        /* Wait till the bus is free */
  43        while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  44                ;
  45
  46        /* Write the value to the register */
  47        out_be32(&regs->mdio_data, MDIO_DATA(value));
  48
  49        /* Wait till the MDIO write is complete */
  50        while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
  51                ;
  52
  53        return 0;
  54}
  55
  56/*
  57 * Reads from register regnum in the PHY for device dev, returning the value.
  58 * Clears miimcom first.  All PHY configuration has to be done through the
  59 * TSEC1 MIIM regs
  60 */
  61static int tgec_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
  62                          int regnum)
  63{
  64        u32 mdio_ctl;
  65        u32 stat_val;
  66        struct tgec_mdio_controller *regs = bus->priv;
  67
  68        if (dev_addr == MDIO_DEVAD_NONE)
  69                return 0xffff;
  70
  71        stat_val = MDIO_STAT_CLKDIV(100);
  72        out_be32(&regs->mdio_stat, stat_val);
  73        /* Wait till the bus is free */
  74        while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  75                ;
  76
  77        /* Set the Port and Device Addrs */
  78        mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
  79        out_be32(&regs->mdio_ctl, mdio_ctl);
  80
  81        /* Set the register address */
  82        out_be32(&regs->mdio_addr, regnum & 0xffff);
  83
  84        /* Wait till the bus is free */
  85        while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  86                ;
  87
  88        /* Initiate the read */
  89        mdio_ctl |= MDIO_CTL_READ;
  90        out_be32(&regs->mdio_ctl, mdio_ctl);
  91
  92        /* Wait till the MDIO write is complete */
  93        while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
  94                ;
  95
  96        /* Return all Fs if nothing was there */
  97        if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
  98                return 0xffff;
  99
 100        return in_be32(&regs->mdio_data) & 0xffff;
 101}
 102
 103static int tgec_mdio_reset(struct mii_dev *bus)
 104{
 105        return 0;
 106}
 107
 108int fm_tgec_mdio_init(struct bd_info *bis, struct tgec_mdio_info *info)
 109{
 110        struct mii_dev *bus = mdio_alloc();
 111
 112        if (!bus) {
 113                printf("Failed to allocate FM TGEC MDIO bus\n");
 114                return -1;
 115        }
 116
 117        bus->read = tgec_mdio_read;
 118        bus->write = tgec_mdio_write;
 119        bus->reset = tgec_mdio_reset;
 120        strcpy(bus->name, info->name);
 121
 122        bus->priv = info->regs;
 123
 124        return mdio_register(bus);
 125}
 126