mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-05-05 09:56:12 +02:00
realtek: mdio: activate multiple busses
The mdio controller inside the Realtek switches drives multiple busses. Until now the driver exposed a flattened single bus (aka port view). Align to the upstream driver and expose up to 4 busses depending on the dts definition. For this: 1. Adapt rtmdio_probe() so it calls rtmdio_probe_one() for each child dts child node that represents a single bus. 2. Adapt rtmdio_probe_one() so it registers a single bus in "full-auto" mode. No more hacks via fwnode_mdiobus_register_phy() needed. 3. Adapt rtmdio_phy_to_port() so it uses a lookup based on the new topology. 4. Adapt rtmdio_get_phy_info() for multiple busses. 5. In the DSA driver adapt the mdio controller load check to wait until all busses have been registered. Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de> Link: https://github.com/openwrt/openwrt/pull/22830 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
87d5b3f7e6
commit
084da38a2e
@ -214,17 +214,24 @@ u64 rtl839x_get_port_reg_le(int reg)
|
||||
static int rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
struct device_node *dn, *phy_node, *pcs_node, *led_node;
|
||||
struct mii_bus *bus;
|
||||
u32 pn;
|
||||
|
||||
/* Check if mdio bus is defined with status "okay" and already registered */
|
||||
/* Check if all busses of Realtek mdio controller are registered */
|
||||
dn = of_find_compatible_node(NULL, NULL, "realtek,otto-mdio");
|
||||
if (!dn || !of_device_is_available(dn))
|
||||
if (!of_device_is_available(dn)) {
|
||||
of_node_put(dn);
|
||||
return -ENODEV;
|
||||
bus = of_mdio_find_bus(dn);
|
||||
if (!bus)
|
||||
return -EPROBE_DEFER;
|
||||
put_device(&bus->dev);
|
||||
}
|
||||
|
||||
for_each_child_of_node_scoped(dn, bn) {
|
||||
struct mii_bus *bus = of_mdio_find_bus(bn);
|
||||
if (!bus) {
|
||||
of_node_put(dn);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
put_device(&bus->dev);
|
||||
}
|
||||
of_node_put(dn);
|
||||
|
||||
dn = of_find_compatible_node(NULL, NULL, "realtek,otto-switch");
|
||||
if (!dn) {
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <linux/fwnode_mdio.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
@ -227,15 +228,15 @@ struct rtmdio_phy_info {
|
||||
|
||||
static int rtmdio_phy_to_port(struct mii_bus *bus, int phy)
|
||||
{
|
||||
struct rtmdio_ctrl *ctrl = rtmdio_ctrl_from_bus(bus);
|
||||
struct rtmdio_chan *chan = bus->priv;
|
||||
struct rtmdio_ctrl *ctrl = chan->ctrl;
|
||||
int pn;
|
||||
|
||||
if (phy < 0 || phy >= ctrl->cfg->num_phys)
|
||||
return -ENOENT;
|
||||
for_each_port(ctrl, pn)
|
||||
if (ctrl->port[pn].smi_bus == chan->smi_bus && ctrl->port[pn].smi_addr == phy)
|
||||
return pn;
|
||||
|
||||
if (!test_bit(phy, ctrl->valid_ports))
|
||||
return -ENOENT;
|
||||
|
||||
return phy;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int rtmdio_run_cmd(struct mii_bus *bus, int cmd, int mask, int regnum, int fail)
|
||||
@ -642,9 +643,10 @@ static u32 rtmdio_get_phy_id(struct phy_device *phydev)
|
||||
|
||||
static int rtmdio_get_phy_info(struct rtmdio_ctrl *ctrl, int pn, struct rtmdio_phy_info *phyinfo)
|
||||
{
|
||||
struct phy_device *phydev = mdiobus_get_phy(ctrl->bus[0].mii_bus, pn);
|
||||
u32 phyid = rtmdio_get_phy_id(phydev);
|
||||
struct mii_bus *bus = ctrl->bus[ctrl->port[pn].smi_bus].mii_bus;
|
||||
int addr = ctrl->port[pn].smi_addr;
|
||||
int ret = 0;
|
||||
u32 phyid;
|
||||
|
||||
/*
|
||||
* Depending on the attached PHY the polling mechanism must be fine tuned. Basically
|
||||
@ -652,6 +654,7 @@ static int rtmdio_get_phy_info(struct rtmdio_ctrl *ctrl, int pn, struct rtmdio_p
|
||||
* features.
|
||||
*/
|
||||
memset(phyinfo, 0, sizeof(*phyinfo));
|
||||
phyid = rtmdio_get_phy_id(mdiobus_get_phy(bus, addr));
|
||||
|
||||
switch(phyid) {
|
||||
case RTMDIO_PHY_AQR113C_A:
|
||||
@ -920,21 +923,26 @@ static int rtmdio_map_ports(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtmdio_probe_one(struct device *dev, struct rtmdio_ctrl *ctrl)
|
||||
static int rtmdio_probe_one(struct device *dev, struct rtmdio_ctrl *ctrl,
|
||||
struct fwnode_handle *node)
|
||||
{
|
||||
struct rtmdio_chan *chan;
|
||||
struct mii_bus *bus;
|
||||
int ret, pn;
|
||||
int smi_bus, ret;
|
||||
|
||||
ret = fwnode_property_read_u32(node, "reg", &smi_bus);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bus = devm_mdiobus_alloc_size(dev, sizeof(*chan));
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
ctrl->bus[smi_bus].mii_bus = bus;
|
||||
|
||||
chan = bus->priv;
|
||||
chan->ctrl = ctrl;
|
||||
|
||||
chan->smi_bus = 0;
|
||||
ctrl->bus[0].mii_bus = bus;
|
||||
chan->smi_bus = smi_bus;
|
||||
|
||||
bus->name = "Realtek MDIO bus";
|
||||
bus->read = rtmdio_read;
|
||||
@ -942,22 +950,11 @@ static int rtmdio_probe_one(struct device *dev, struct rtmdio_ctrl *ctrl)
|
||||
bus->read_c45 = rtmdio_read_c45;
|
||||
bus->write_c45 = rtmdio_write_c45;
|
||||
bus->parent = dev;
|
||||
bus->phy_mask = ~0;
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "realtek-mdio");
|
||||
device_set_node(&bus->dev, of_fwnode_handle(dev->of_node));
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "realtek-mdio-%d", smi_bus);
|
||||
|
||||
ret = devm_mdiobus_register(dev, bus);
|
||||
ret = devm_of_mdiobus_register(dev, bus, to_of_node(node));
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "cannot register MDIO bus\n");
|
||||
|
||||
for_each_port(ctrl, pn) {
|
||||
if (!ret)
|
||||
ret = fwnode_mdiobus_register_phy(bus,
|
||||
of_fwnode_handle(ctrl->port[pn].dn), pn);
|
||||
of_node_put(ctrl->port[pn].dn);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "cannot register MDIO %d bus\n", smi_bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -991,9 +988,11 @@ static int rtmdio_probe(struct platform_device *pdev)
|
||||
rtmdio_setup_smi_topology(ctrl);
|
||||
ctrl->cfg->setup_ctrl(ctrl);
|
||||
|
||||
ret = rtmdio_probe_one(dev, ctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
device_for_each_child_node_scoped(dev, child) {
|
||||
ret = rtmdio_probe_one(dev, ctrl, child);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ctrl->cfg->setup_polling)
|
||||
ctrl->cfg->setup_polling(ctrl);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user