1 // SPDX-License-Identifier: GPL-2.0
3 * MDIO bus driver for the Xilinx TEMAC device
5 * Copyright (c) 2009 Secret Lab Technologies, Ltd.
9 #include <linux/netdevice.h>
10 #include <linux/mutex.h>
11 #include <linux/phy.h>
13 #include <linux/of_device.h>
14 #include <linux/of_address.h>
15 #include <linux/slab.h>
16 #include <linux/of_mdio.h>
20 /* ---------------------------------------------------------------------
23 static int temac_mdio_read(struct mii_bus
*bus
, int phy_id
, int reg
)
25 struct temac_local
*lp
= bus
->priv
;
28 /* Write the PHY address to the MIIM Access Initiator register.
29 * When the transfer completes, the PHY register value will appear
30 * in the LSW0 register */
31 mutex_lock(&lp
->indirect_mutex
);
32 temac_iow(lp
, XTE_LSW0_OFFSET
, (phy_id
<< 5) | reg
);
33 rc
= temac_indirect_in32(lp
, XTE_MIIMAI_OFFSET
);
34 mutex_unlock(&lp
->indirect_mutex
);
36 dev_dbg(lp
->dev
, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n",
42 static int temac_mdio_write(struct mii_bus
*bus
, int phy_id
, int reg
, u16 val
)
44 struct temac_local
*lp
= bus
->priv
;
46 dev_dbg(lp
->dev
, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
49 /* First write the desired value into the write data register
50 * and then write the address into the access initiator register
52 mutex_lock(&lp
->indirect_mutex
);
53 temac_indirect_out32(lp
, XTE_MGTDR_OFFSET
, val
);
54 temac_indirect_out32(lp
, XTE_MIIMAI_OFFSET
, (phy_id
<< 5) | reg
);
55 mutex_unlock(&lp
->indirect_mutex
);
60 int temac_mdio_setup(struct temac_local
*lp
, struct device_node
*np
)
68 /* Calculate a reasonable divisor for the clock rate */
69 clk_div
= 0x3f; /* worst-case default setting */
70 if (of_property_read_u32(np
, "clock-frequency", &bus_hz
) == 0) {
71 clk_div
= bus_hz
/ (2500 * 1000 * 2) - 1;
78 /* Enable the MDIO bus by asserting the enable bit and writing
79 * in the clock config */
80 mutex_lock(&lp
->indirect_mutex
);
81 temac_indirect_out32(lp
, XTE_MC_OFFSET
, 1 << 6 | clk_div
);
82 mutex_unlock(&lp
->indirect_mutex
);
84 bus
= mdiobus_alloc();
88 of_address_to_resource(np
, 0, &res
);
89 snprintf(bus
->id
, MII_BUS_ID_SIZE
, "%.8llx",
90 (unsigned long long)res
.start
);
92 bus
->name
= "Xilinx TEMAC MDIO";
93 bus
->read
= temac_mdio_read
;
94 bus
->write
= temac_mdio_write
;
95 bus
->parent
= lp
->dev
;
99 rc
= of_mdiobus_register(bus
, np
);
103 mutex_lock(&lp
->indirect_mutex
);
104 dev_dbg(lp
->dev
, "MDIO bus registered; MC:%x\n",
105 temac_indirect_in32(lp
, XTE_MC_OFFSET
));
106 mutex_unlock(&lp
->indirect_mutex
);
114 void temac_mdio_teardown(struct temac_local
*lp
)
116 mdiobus_unregister(lp
->mii_bus
);
117 mdiobus_free(lp
->mii_bus
);