]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/net/ll_temac_mdio.c
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/of_address.h>
14 #include <linux/slab.h>
15 #include <linux/of_mdio.h>
19 /* ---------------------------------------------------------------------
22 static int temac_mdio_read(struct mii_bus
*bus
, int phy_id
, int reg
)
24 struct temac_local
*lp
= bus
->priv
;
27 /* Write the PHY address to the MIIM Access Initiator register.
28 * When the transfer completes, the PHY register value will appear
29 * in the LSW0 register */
30 mutex_lock(&lp
->indirect_mutex
);
31 temac_iow(lp
, XTE_LSW0_OFFSET
, (phy_id
<< 5) | reg
);
32 rc
= temac_indirect_in32(lp
, XTE_MIIMAI_OFFSET
);
33 mutex_unlock(&lp
->indirect_mutex
);
35 dev_dbg(lp
->dev
, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n",
41 static int temac_mdio_write(struct mii_bus
*bus
, int phy_id
, int reg
, u16 val
)
43 struct temac_local
*lp
= bus
->priv
;
45 dev_dbg(lp
->dev
, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
48 /* First write the desired value into the write data register
49 * and then write the address into the access initiator register
51 mutex_lock(&lp
->indirect_mutex
);
52 temac_indirect_out32(lp
, XTE_MGTDR_OFFSET
, val
);
53 temac_indirect_out32(lp
, XTE_MIIMAI_OFFSET
, (phy_id
<< 5) | reg
);
54 mutex_unlock(&lp
->indirect_mutex
);
59 int temac_mdio_setup(struct temac_local
*lp
, struct device_node
*np
)
67 /* Calculate a reasonable divisor for the clock rate */
68 clk_div
= 0x3f; /* worst-case default setting */
69 bus_hz
= of_get_property(np
, "clock-frequency", &size
);
70 if (bus_hz
&& size
>= sizeof(*bus_hz
)) {
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
;
96 bus
->irq
= lp
->mdio_irqs
; /* preallocated IRQ table */
100 rc
= of_mdiobus_register(bus
, np
);
104 mutex_lock(&lp
->indirect_mutex
);
105 dev_dbg(lp
->dev
, "MDIO bus registered; MC:%x\n",
106 temac_indirect_in32(lp
, XTE_MC_OFFSET
));
107 mutex_unlock(&lp
->indirect_mutex
);
115 void temac_mdio_teardown(struct temac_local
*lp
)
117 mdiobus_unregister(lp
->mii_bus
);
118 kfree(lp
->mii_bus
->irq
);
119 mdiobus_free(lp
->mii_bus
);