uboot/drivers/net/fsl_enetc_mdio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * ENETC ethernet controller driver
   4 * Copyright 2019 NXP
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <pci.h>
  11#include <miiphy.h>
  12#include <asm/io.h>
  13#include <asm/processor.h>
  14#include <miiphy.h>
  15
  16#include "fsl_enetc.h"
  17
  18static void enetc_mdio_wait_bsy(struct enetc_mdio_priv *priv)
  19{
  20        int to = 10000;
  21
  22        while ((enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_BSY) &&
  23               --to)
  24                cpu_relax();
  25        if (!to)
  26                printf("T");
  27}
  28
  29int enetc_mdio_read_priv(struct enetc_mdio_priv *priv, int addr, int devad,
  30                         int reg)
  31{
  32        if (devad == MDIO_DEVAD_NONE)
  33                enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
  34        else
  35                enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
  36        enetc_mdio_wait_bsy(priv);
  37
  38        if (devad == MDIO_DEVAD_NONE) {
  39                enetc_write(priv, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
  40                            (addr << 5) | reg);
  41        } else {
  42                enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + devad);
  43                enetc_mdio_wait_bsy(priv);
  44
  45                enetc_write(priv, ENETC_MDIO_STAT, reg);
  46                enetc_mdio_wait_bsy(priv);
  47
  48                enetc_write(priv, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
  49                            (addr << 5) | devad);
  50        }
  51
  52        enetc_mdio_wait_bsy(priv);
  53        if (enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_RD_ER)
  54                return ENETC_MDIO_READ_ERR;
  55
  56        return enetc_read(priv, ENETC_MDIO_DATA);
  57}
  58
  59int enetc_mdio_write_priv(struct enetc_mdio_priv *priv, int addr, int devad,
  60                          int reg, u16 val)
  61{
  62        if (devad == MDIO_DEVAD_NONE)
  63                enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
  64        else
  65                enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
  66        enetc_mdio_wait_bsy(priv);
  67
  68        if (devad != MDIO_DEVAD_NONE) {
  69                enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + devad);
  70                enetc_write(priv, ENETC_MDIO_STAT, reg);
  71        } else {
  72                enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + reg);
  73        }
  74        enetc_mdio_wait_bsy(priv);
  75
  76        enetc_write(priv, ENETC_MDIO_DATA, val);
  77        enetc_mdio_wait_bsy(priv);
  78
  79        return 0;
  80}
  81
  82/* DM wrappers */
  83static int dm_enetc_mdio_read(struct udevice *dev, int addr, int devad, int reg)
  84{
  85        struct enetc_mdio_priv *priv = dev_get_priv(dev);
  86
  87        return enetc_mdio_read_priv(priv, addr, devad, reg);
  88}
  89
  90static int dm_enetc_mdio_write(struct udevice *dev, int addr, int devad,
  91                               int reg, u16 val)
  92{
  93        struct enetc_mdio_priv *priv = dev_get_priv(dev);
  94
  95        return enetc_mdio_write_priv(priv, addr, devad, reg, val);
  96}
  97
  98static const struct mdio_ops enetc_mdio_ops = {
  99        .read = dm_enetc_mdio_read,
 100        .write = dm_enetc_mdio_write,
 101};
 102
 103static int enetc_mdio_bind(struct udevice *dev)
 104{
 105        char name[16];
 106        static int eth_num_devices;
 107
 108        /*
 109         * prefer using PCI function numbers to number interfaces, but these
 110         * are only available if dts nodes are present.  For PCI they are
 111         * optional, handle that case too.  Just in case some nodes are present
 112         * and some are not, use different naming scheme - enetc-N based on
 113         * PCI function # and enetc#N based on interface count
 114         */
 115        if (ofnode_valid(dev->node))
 116                sprintf(name, "emdio-%u", PCI_FUNC(pci_get_devfn(dev)));
 117        else
 118                sprintf(name, "emdio#%u", eth_num_devices++);
 119        device_set_name(dev, name);
 120
 121        return 0;
 122}
 123
 124static int enetc_mdio_probe(struct udevice *dev)
 125{
 126        struct enetc_mdio_priv *priv = dev_get_priv(dev);
 127
 128        priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
 129        if (!priv->regs_base) {
 130                enetc_dbg(dev, "failed to map BAR0\n");
 131                return -EINVAL;
 132        }
 133
 134        priv->regs_base += ENETC_MDIO_BASE;
 135
 136        dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);
 137
 138        return 0;
 139}
 140
 141U_BOOT_DRIVER(enetc_mdio) = {
 142        .name   = "enetc_mdio",
 143        .id     = UCLASS_MDIO,
 144        .bind   = enetc_mdio_bind,
 145        .probe  = enetc_mdio_probe,
 146        .ops    = &enetc_mdio_ops,
 147        .priv_auto_alloc_size = sizeof(struct enetc_mdio_priv),
 148};
 149
 150static struct pci_device_id enetc_mdio_ids[] = {
 151        { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_MDIO) },
 152        { }
 153};
 154
 155U_BOOT_PCI_DEVICE(enetc_mdio, enetc_mdio_ids);
 156