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