uboot/drivers/net/fm/tgec_phy.c
<<
>>
Prefs
   1/*
   2 * Copyright 2009-2011 Freescale Semiconductor, Inc.
   3 *      Andy Fleming <afleming@freescale.com>
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation; either version 2 of
   8 * the License, or (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  18 * MA 02111-1307 USA
  19 * Some part is taken from tsec.c
  20 */
  21#include <common.h>
  22#include <miiphy.h>
  23#include <phy.h>
  24#include <asm/io.h>
  25#include <asm/fsl_tgec.h>
  26#include <fm_eth.h>
  27
  28/*
  29 * Write value to the PHY for this device to the register at regnum, waiting
  30 * until the write is done before it returns.  All PHY configuration has to be
  31 * done through the TSEC1 MIIM regs
  32 */
  33int tgec_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
  34                        int regnum, u16 value)
  35{
  36        u32 mdio_ctl;
  37        u32 stat_val;
  38        struct tgec_mdio_controller *regs = bus->priv;
  39
  40        if (dev_addr == MDIO_DEVAD_NONE)
  41                return 0;
  42
  43        /* Wait till the bus is free */
  44        stat_val = MDIO_STAT_CLKDIV(100);
  45        out_be32(&regs->mdio_stat, stat_val);
  46        while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  47                ;
  48
  49        /* Set the port and dev addr */
  50        mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
  51        out_be32(&regs->mdio_ctl, mdio_ctl);
  52
  53        /* Set the register address */
  54        out_be32(&regs->mdio_addr, regnum & 0xffff);
  55
  56        /* Wait till the bus is free */
  57        while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  58                ;
  59
  60        /* Write the value to the register */
  61        out_be32(&regs->mdio_data, MDIO_DATA(value));
  62
  63        /* Wait till the MDIO write is complete */
  64        while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
  65                ;
  66
  67        return 0;
  68}
  69
  70/*
  71 * Reads from register regnum in the PHY for device dev, returning the value.
  72 * Clears miimcom first.  All PHY configuration has to be done through the
  73 * TSEC1 MIIM regs
  74 */
  75int tgec_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
  76                        int regnum)
  77{
  78        u32 mdio_ctl;
  79        u32 stat_val;
  80        struct tgec_mdio_controller *regs = bus->priv;
  81
  82        if (dev_addr == MDIO_DEVAD_NONE)
  83                return 0xffff;
  84
  85        stat_val = MDIO_STAT_CLKDIV(100);
  86        out_be32(&regs->mdio_stat, stat_val);
  87        /* Wait till the bus is free */
  88        while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  89                ;
  90
  91        /* Set the Port and Device Addrs */
  92        mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
  93        out_be32(&regs->mdio_ctl, mdio_ctl);
  94
  95        /* Set the register address */
  96        out_be32(&regs->mdio_addr, regnum & 0xffff);
  97
  98        /* Wait till the bus is free */
  99        while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
 100                ;
 101
 102        /* Initiate the read */
 103        mdio_ctl |= MDIO_CTL_READ;
 104        out_be32(&regs->mdio_ctl, mdio_ctl);
 105
 106        /* Wait till the MDIO write is complete */
 107        while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
 108                ;
 109
 110        /* Return all Fs if nothing was there */
 111        if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
 112                return 0xffff;
 113
 114        return in_be32(&regs->mdio_data) & 0xffff;
 115}
 116
 117int tgec_mdio_reset(struct mii_dev *bus)
 118{
 119        return 0;
 120}
 121
 122int fm_tgec_mdio_init(bd_t *bis, struct tgec_mdio_info *info)
 123{
 124        struct mii_dev *bus = mdio_alloc();
 125
 126        if (!bus) {
 127                printf("Failed to allocate FM TGEC MDIO bus\n");
 128                return -1;
 129        }
 130
 131        bus->read = tgec_mdio_read;
 132        bus->write = tgec_mdio_write;
 133        bus->reset = tgec_mdio_reset;
 134        sprintf(bus->name, info->name);
 135
 136        bus->priv = info->regs;
 137
 138        return mdio_register(bus);
 139}
 140