root/drivers/net/ethernet/xilinx/ll_temac_mdio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. temac_mdio_read
  2. temac_mdio_write
  3. temac_mdio_setup
  4. temac_mdio_teardown

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * MDIO bus driver for the Xilinx TEMAC device
   4  *
   5  * Copyright (c) 2009 Secret Lab Technologies, Ltd.
   6  */
   7 
   8 #include <linux/io.h>
   9 #include <linux/netdevice.h>
  10 #include <linux/mutex.h>
  11 #include <linux/phy.h>
  12 #include <linux/of.h>
  13 #include <linux/of_device.h>
  14 #include <linux/of_address.h>
  15 #include <linux/slab.h>
  16 #include <linux/of_mdio.h>
  17 #include <linux/platform_data/xilinx-ll-temac.h>
  18 
  19 #include "ll_temac.h"
  20 
  21 /* ---------------------------------------------------------------------
  22  * MDIO Bus functions
  23  */
  24 static int temac_mdio_read(struct mii_bus *bus, int phy_id, int reg)
  25 {
  26         struct temac_local *lp = bus->priv;
  27         u32 rc;
  28         unsigned long flags;
  29 
  30         /* Write the PHY address to the MIIM Access Initiator register.
  31          * When the transfer completes, the PHY register value will appear
  32          * in the LSW0 register */
  33         spin_lock_irqsave(lp->indirect_lock, flags);
  34         temac_iow(lp, XTE_LSW0_OFFSET, (phy_id << 5) | reg);
  35         rc = temac_indirect_in32_locked(lp, XTE_MIIMAI_OFFSET);
  36         spin_unlock_irqrestore(lp->indirect_lock, flags);
  37 
  38         dev_dbg(lp->dev, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n",
  39                 phy_id, reg, rc);
  40 
  41         return rc;
  42 }
  43 
  44 static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
  45 {
  46         struct temac_local *lp = bus->priv;
  47         unsigned long flags;
  48 
  49         dev_dbg(lp->dev, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
  50                 phy_id, reg, val);
  51 
  52         /* First write the desired value into the write data register
  53          * and then write the address into the access initiator register
  54          */
  55         spin_lock_irqsave(lp->indirect_lock, flags);
  56         temac_indirect_out32_locked(lp, XTE_MGTDR_OFFSET, val);
  57         temac_indirect_out32_locked(lp, XTE_MIIMAI_OFFSET, (phy_id << 5) | reg);
  58         spin_unlock_irqrestore(lp->indirect_lock, flags);
  59 
  60         return 0;
  61 }
  62 
  63 int temac_mdio_setup(struct temac_local *lp, struct platform_device *pdev)
  64 {
  65         struct ll_temac_platform_data *pdata = dev_get_platdata(&pdev->dev);
  66         struct device_node *np = dev_of_node(&pdev->dev);
  67         struct mii_bus *bus;
  68         u32 bus_hz;
  69         int clk_div;
  70         int rc;
  71         struct resource res;
  72 
  73         /* Get MDIO bus frequency (if specified) */
  74         bus_hz = 0;
  75         if (np)
  76                 of_property_read_u32(np, "clock-frequency", &bus_hz);
  77         else if (pdata)
  78                 bus_hz = pdata->mdio_clk_freq;
  79 
  80         /* Calculate a reasonable divisor for the clock rate */
  81         clk_div = 0x3f; /* worst-case default setting */
  82         if (bus_hz != 0) {
  83                 clk_div = bus_hz / (2500 * 1000 * 2) - 1;
  84                 if (clk_div < 1)
  85                         clk_div = 1;
  86                 if (clk_div > 0x3f)
  87                         clk_div = 0x3f;
  88         }
  89 
  90         /* Enable the MDIO bus by asserting the enable bit and writing
  91          * in the clock config */
  92         temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div);
  93 
  94         bus = devm_mdiobus_alloc(&pdev->dev);
  95         if (!bus)
  96                 return -ENOMEM;
  97 
  98         if (np) {
  99                 of_address_to_resource(np, 0, &res);
 100                 snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
 101                          (unsigned long long)res.start);
 102         } else if (pdata) {
 103                 snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
 104                          pdata->mdio_bus_id);
 105         }
 106 
 107         bus->priv = lp;
 108         bus->name = "Xilinx TEMAC MDIO";
 109         bus->read = temac_mdio_read;
 110         bus->write = temac_mdio_write;
 111         bus->parent = lp->dev;
 112 
 113         lp->mii_bus = bus;
 114 
 115         rc = of_mdiobus_register(bus, np);
 116         if (rc)
 117                 return rc;
 118 
 119         dev_dbg(lp->dev, "MDIO bus registered;  MC:%x\n",
 120                 temac_indirect_in32(lp, XTE_MC_OFFSET));
 121         return 0;
 122 }
 123 
 124 void temac_mdio_teardown(struct temac_local *lp)
 125 {
 126         mdiobus_unregister(lp->mii_bus);
 127 }

/* [<][>][^][v][top][bottom][index][help] */