2 * MDIO bus driver for the Xilinx TEMAC device
4 * Copyright (c) 2009 Secret Lab Technologies, Ltd.
8 #include <linux/netdevice.h>
9 #include <linux/mutex.h>
10 #include <linux/phy.h>
12 #include <linux/of_device.h>
13 #include <linux/slab.h>
14 #include <linux/of_mdio.h>
18 /* ---------------------------------------------------------------------
21 static int temac_mdio_read(struct mii_bus
*bus
, int phy_id
, int reg
)
23 struct temac_local
*lp
= bus
->priv
;
26 /* Write the PHY address to the MIIM Access Initiator register.
27 * When the transfer completes, the PHY register value will appear
28 * in the LSW0 register */
29 mutex_lock(&lp
->indirect_mutex
);
30 temac_iow(lp
, XTE_LSW0_OFFSET
, (phy_id
<< 5) | reg
);
31 rc
= temac_indirect_in32(lp
, XTE_MIIMAI_OFFSET
);
32 mutex_unlock(&lp
->indirect_mutex
);
34 dev_dbg(lp
->dev
, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n",
40 static int temac_mdio_write(struct mii_bus
*bus
, int phy_id
, int reg
, u16 val
)
42 struct temac_local
*lp
= bus
->priv
;
44 dev_dbg(lp
->dev
, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
47 /* First write the desired value into the write data register
48 * and then write the address into the access initiator register
50 mutex_lock(&lp
->indirect_mutex
);
51 temac_indirect_out32(lp
, XTE_MGTDR_OFFSET
, val
);
52 temac_indirect_out32(lp
, XTE_MIIMAI_OFFSET
, (phy_id
<< 5) | reg
);
53 mutex_unlock(&lp
->indirect_mutex
);
58 int temac_mdio_setup(struct temac_local
*lp
, struct device_node
*np
)
66 /* Calculate a reasonable divisor for the clock rate */
67 clk_div
= 0x3f; /* worst-case default setting */
68 bus_hz
= of_get_property(np
, "clock-frequency", &size
);
69 if (bus_hz
&& size
>= sizeof(*bus_hz
)) {
70 clk_div
= (*bus_hz
) / (2500 * 1000 * 2) - 1;
77 /* Enable the MDIO bus by asserting the enable bit and writing
78 * in the clock config */
79 mutex_lock(&lp
->indirect_mutex
);
80 temac_indirect_out32(lp
, XTE_MC_OFFSET
, 1 << 6 | clk_div
);
81 mutex_unlock(&lp
->indirect_mutex
);
83 bus
= mdiobus_alloc();
87 of_address_to_resource(np
, 0, &res
);
88 snprintf(bus
->id
, MII_BUS_ID_SIZE
, "%.8llx",
89 (unsigned long long)res
.start
);
91 bus
->name
= "Xilinx TEMAC MDIO";
92 bus
->read
= temac_mdio_read
;
93 bus
->write
= temac_mdio_write
;
94 bus
->parent
= lp
->dev
;
95 bus
->irq
= lp
->mdio_irqs
; /* preallocated IRQ table */
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 kfree(lp
->mii_bus
->irq
);
118 mdiobus_free(lp
->mii_bus
);