uboot/drivers/net/fsl_mdio.c
<<
>>
Prefs
   1/*
   2 * Copyright 2009-2010, 2013 Freescale Semiconductor, Inc.
   3 *      Jun-jie Zhang <b18070@freescale.com>
   4 *      Mingkai Hu <Mingkai.hu@freescale.com>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <miiphy.h>
  11#include <phy.h>
  12#include <fsl_mdio.h>
  13#include <asm/io.h>
  14#include <linux/errno.h>
  15
  16void tsec_local_mdio_write(struct tsec_mii_mng __iomem *phyregs, int port_addr,
  17                int dev_addr, int regnum, int value)
  18{
  19        int timeout = 1000000;
  20
  21        out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
  22        out_be32(&phyregs->miimcon, value);
  23        /* Memory barrier */
  24        mb();
  25
  26        while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--)
  27                ;
  28}
  29
  30int tsec_local_mdio_read(struct tsec_mii_mng __iomem *phyregs, int port_addr,
  31                int dev_addr, int regnum)
  32{
  33        int value;
  34        int timeout = 1000000;
  35
  36        /* Put the address of the phy, and the register number into MIIMADD */
  37        out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
  38
  39        /* Clear the command register, and wait */
  40        out_be32(&phyregs->miimcom, 0);
  41        /* Memory barrier */
  42        mb();
  43
  44        /* Initiate a read command, and wait */
  45        out_be32(&phyregs->miimcom, MIIMCOM_READ_CYCLE);
  46        /* Memory barrier */
  47        mb();
  48
  49        /* Wait for the the indication that the read is done */
  50        while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
  51                        && timeout--)
  52                ;
  53
  54        /* Grab the value read from the PHY */
  55        value = in_be32(&phyregs->miimstat);
  56
  57        return value;
  58}
  59
  60static int fsl_pq_mdio_reset(struct mii_dev *bus)
  61{
  62        struct tsec_mii_mng __iomem *regs =
  63                (struct tsec_mii_mng __iomem *)bus->priv;
  64
  65        /* Reset MII (due to new addresses) */
  66        out_be32(&regs->miimcfg, MIIMCFG_RESET_MGMT);
  67
  68        out_be32(&regs->miimcfg, MIIMCFG_INIT_VALUE);
  69
  70        while (in_be32(&regs->miimind) & MIIMIND_BUSY)
  71                ;
  72
  73        return 0;
  74}
  75
  76int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum)
  77{
  78        struct tsec_mii_mng __iomem *phyregs =
  79                (struct tsec_mii_mng __iomem *)bus->priv;
  80
  81        return tsec_local_mdio_read(phyregs, addr, dev_addr, regnum);
  82}
  83
  84int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum,
  85                        u16 value)
  86{
  87        struct tsec_mii_mng __iomem *phyregs =
  88                (struct tsec_mii_mng __iomem *)bus->priv;
  89
  90        tsec_local_mdio_write(phyregs, addr, dev_addr, regnum, value);
  91
  92        return 0;
  93}
  94
  95int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info)
  96{
  97        struct mii_dev *bus = mdio_alloc();
  98
  99        if (!bus) {
 100                printf("Failed to allocate FSL MDIO bus\n");
 101                return -1;
 102        }
 103
 104        bus->read = tsec_phy_read;
 105        bus->write = tsec_phy_write;
 106        bus->reset = fsl_pq_mdio_reset;
 107        strcpy(bus->name, info->name);
 108
 109        bus->priv = (void *)info->regs;
 110
 111        return mdio_register(bus);
 112}
 113