mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
net: dsa: microchip: implement lan937x-specific MDIO registration
All the switches use a common mdio_register() function that uses two
ksz_dev_ops callbacks (.mdio_bus_preinit() and .create_phy_addr_map())
to handle the lan937x specific case. These two callbacks are used only
at this place in the code.
Implement a new lan937x-specific MDIO registration functions that uses
these two lan937x-specific functions. The lan937x bindings don't
have any 'interrupts' property so this lan937x_mdio_register() doesn't
call ksz_irq_phy_setup().
Expose the common ksz_*_mdio_{read/write} functions so they can be used
in lan937x.c
Remove the callbacks from ksz_dev_ops.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
Link: https://patch.msgid.link/20260608-clean-ksz-3rd-v2-9-6e61b7be23c4@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
e33c168436
commit
03d10c7768
|
|
@ -2256,7 +2256,7 @@ static void ksz_update_port_member(struct ksz_device *dev, int port)
|
|||
dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port);
|
||||
}
|
||||
|
||||
static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
{
|
||||
struct ksz_device *dev = bus->priv;
|
||||
struct dsa_switch *ds = dev->ds;
|
||||
|
|
@ -2264,8 +2264,7 @@ static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
|||
return ds->ops->phy_read(ds, addr, regnum);
|
||||
}
|
||||
|
||||
static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
|
||||
u16 val)
|
||||
int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
|
||||
{
|
||||
struct ksz_device *dev = bus->priv;
|
||||
struct dsa_switch *ds = dev->ds;
|
||||
|
|
@ -2286,7 +2285,7 @@ static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
|
|||
*
|
||||
* Return: Value of the PHY register, or a negative error code on failure.
|
||||
*/
|
||||
static int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
{
|
||||
struct ksz_device *dev = bus->priv;
|
||||
|
||||
|
|
@ -2306,8 +2305,7 @@ static int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
|||
*
|
||||
* Return: 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
static int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum,
|
||||
u16 val)
|
||||
int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
|
||||
{
|
||||
struct ksz_device *dev = bus->priv;
|
||||
|
||||
|
|
@ -2415,8 +2413,8 @@ static void ksz_irq_phy_free(struct ksz_device *dev)
|
|||
*
|
||||
* Return: 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
static int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
|
||||
struct device_node *mdio_np)
|
||||
int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
|
||||
struct device_node *mdio_np)
|
||||
{
|
||||
struct device_node *phy_node, *phy_parent_node;
|
||||
bool phys_are_valid = true;
|
||||
|
|
@ -2519,20 +2517,8 @@ int ksz_mdio_register(struct ksz_device *dev)
|
|||
goto put_mdio_node;
|
||||
}
|
||||
|
||||
if (dev->dev_ops->mdio_bus_preinit) {
|
||||
ret = dev->dev_ops->mdio_bus_preinit(dev, !!parent_bus);
|
||||
if (ret)
|
||||
goto put_mdio_node;
|
||||
}
|
||||
|
||||
if (dev->dev_ops->create_phy_addr_map) {
|
||||
ret = dev->dev_ops->create_phy_addr_map(dev, !!parent_bus);
|
||||
if (ret)
|
||||
goto put_mdio_node;
|
||||
} else {
|
||||
for (i = 0; i < dev->info->port_cnt; i++)
|
||||
dev->phy_addr_map[i] = i;
|
||||
}
|
||||
for (i = 0; i < dev->info->port_cnt; i++)
|
||||
dev->phy_addr_map[i] = i;
|
||||
|
||||
bus->priv = dev;
|
||||
if (parent_bus) {
|
||||
|
|
|
|||
|
|
@ -366,42 +366,6 @@ struct ksz_dev_ops {
|
|||
u32 (*get_port_addr)(int port, int offset);
|
||||
void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
|
||||
|
||||
/**
|
||||
* @mdio_bus_preinit: Function pointer to pre-initialize the MDIO bus
|
||||
* for accessing PHYs.
|
||||
* @dev: Pointer to device structure.
|
||||
* @side_mdio: Boolean indicating if the PHYs are accessed over a side
|
||||
* MDIO bus.
|
||||
*
|
||||
* This function pointer is used to configure the MDIO bus for PHY
|
||||
* access before initiating regular PHY operations. It enables either
|
||||
* SPI/I2C or side MDIO access modes by unlocking necessary registers
|
||||
* and setting up access permissions for the selected mode.
|
||||
*
|
||||
* Return:
|
||||
* - 0 on success.
|
||||
* - Negative error code on failure.
|
||||
*/
|
||||
int (*mdio_bus_preinit)(struct ksz_device *dev, bool side_mdio);
|
||||
|
||||
/**
|
||||
* @create_phy_addr_map: Function pointer to create a port-to-PHY
|
||||
* address map.
|
||||
* @dev: Pointer to device structure.
|
||||
* @side_mdio: Boolean indicating if the PHYs are accessed over a side
|
||||
* MDIO bus.
|
||||
*
|
||||
* This function pointer is responsible for mapping switch ports to PHY
|
||||
* addresses according to the configured access mode (SPI or side MDIO)
|
||||
* and the device’s strap configuration. The mapping setup may vary
|
||||
* depending on the chip variant and configuration. Ensures the correct
|
||||
* address mapping for PHY communication.
|
||||
*
|
||||
* Return:
|
||||
* - 0 on success.
|
||||
* - Negative error code on failure (e.g., invalid configuration).
|
||||
*/
|
||||
int (*create_phy_addr_map)(struct ksz_device *dev, bool side_mdio);
|
||||
void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
|
||||
u64 *cnt);
|
||||
void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
|
||||
|
|
@ -498,6 +462,12 @@ int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
|
|||
int ksz_suspend(struct dsa_switch *ds);
|
||||
int ksz_resume(struct dsa_switch *ds);
|
||||
|
||||
int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
|
||||
struct device_node *mdio_np);
|
||||
int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum);
|
||||
int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val);
|
||||
int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum);
|
||||
int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val);
|
||||
int ksz_mdio_register(struct ksz_device *dev);
|
||||
int ksz_pirq_setup(struct ksz_device *dev, u8 p);
|
||||
int ksz_girq_setup(struct ksz_device *dev);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
|
@ -669,6 +670,101 @@ static int lan937x_switch_init(struct ksz_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lan937x_mdio_register - Register and configure the MDIO bus for the LAN937x.
|
||||
* @dev: Pointer to the KSZ device structure.
|
||||
*
|
||||
* This function sets up and registers an MDIO bus for a LAN937x switch,
|
||||
* allowing access to its internal PHYs. If the device supports side MDIO,
|
||||
* the function will configure the external MDIO controller specified by the
|
||||
* "mdio-parent-bus" device tree property to directly manage internal PHYs.
|
||||
* Otherwise, SPI or I2C access is set up for PHY access.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
static int lan937x_mdio_register(struct ksz_device *dev)
|
||||
{
|
||||
struct device_node *parent_bus_node;
|
||||
struct mii_bus *parent_bus = NULL;
|
||||
struct dsa_switch *ds = dev->ds;
|
||||
struct device_node *mdio_np;
|
||||
struct mii_bus *bus;
|
||||
int ret;
|
||||
|
||||
mdio_np = of_get_child_by_name(dev->dev->of_node, "mdio");
|
||||
if (!mdio_np)
|
||||
return 0;
|
||||
|
||||
parent_bus_node = of_parse_phandle(mdio_np, "mdio-parent-bus", 0);
|
||||
if (parent_bus_node && !dev->info->phy_side_mdio_supported) {
|
||||
dev_err(dev->dev, "Side MDIO bus is not supported for this HW, ignoring 'mdio-parent-bus' property.\n");
|
||||
ret = -EINVAL;
|
||||
|
||||
goto put_mdio_node;
|
||||
} else if (parent_bus_node) {
|
||||
parent_bus = of_mdio_find_bus(parent_bus_node);
|
||||
if (!parent_bus) {
|
||||
ret = -EPROBE_DEFER;
|
||||
|
||||
goto put_mdio_node;
|
||||
}
|
||||
|
||||
dev->parent_mdio_bus = parent_bus;
|
||||
}
|
||||
|
||||
bus = devm_mdiobus_alloc(ds->dev);
|
||||
if (!bus) {
|
||||
ret = -ENOMEM;
|
||||
goto put_mdio_node;
|
||||
}
|
||||
|
||||
ret = lan937x_mdio_bus_preinit(dev, !!parent_bus);
|
||||
if (ret)
|
||||
goto put_mdio_node;
|
||||
|
||||
ret = lan937x_create_phy_addr_map(dev, !!parent_bus);
|
||||
if (ret)
|
||||
goto put_mdio_node;
|
||||
|
||||
bus->priv = dev;
|
||||
if (parent_bus) {
|
||||
bus->read = ksz_parent_mdio_read;
|
||||
bus->write = ksz_parent_mdio_write;
|
||||
bus->name = "KSZ side MDIO";
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "ksz-side-mdio-%d",
|
||||
ds->index);
|
||||
} else {
|
||||
bus->read = ksz_sw_mdio_read;
|
||||
bus->write = ksz_sw_mdio_write;
|
||||
bus->name = "ksz user smi";
|
||||
if (ds->dst->index != 0)
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d-%d",
|
||||
ds->dst->index, ds->index);
|
||||
else
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
|
||||
}
|
||||
|
||||
ret = ksz_parse_dt_phy_config(dev, bus, mdio_np);
|
||||
if (ret)
|
||||
goto put_mdio_node;
|
||||
|
||||
ds->phys_mii_mask = bus->phy_mask;
|
||||
bus->parent = ds->dev;
|
||||
|
||||
ds->user_mii_bus = bus;
|
||||
|
||||
ret = devm_of_mdiobus_register(ds->dev, bus, mdio_np);
|
||||
if (ret)
|
||||
dev_err(ds->dev, "unable to register MDIO bus %s\n",
|
||||
bus->id);
|
||||
|
||||
put_mdio_node:
|
||||
of_node_put(mdio_np);
|
||||
of_node_put(parent_bus_node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lan937x_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
|
@ -782,7 +878,7 @@ static int lan937x_setup(struct dsa_switch *ds)
|
|||
goto port_release;
|
||||
}
|
||||
|
||||
ret = ksz_mdio_register(dev);
|
||||
ret = lan937x_mdio_register(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to register the mdio");
|
||||
goto out_ptp_clock_unregister;
|
||||
|
|
@ -845,8 +941,6 @@ const struct phylink_mac_ops lan937x_phylink_mac_ops = {
|
|||
const struct ksz_dev_ops lan937x_dev_ops = {
|
||||
.get_port_addr = ksz9477_get_port_addr,
|
||||
.cfg_port_member = ksz9477_cfg_port_member,
|
||||
.mdio_bus_preinit = lan937x_mdio_bus_preinit,
|
||||
.create_phy_addr_map = lan937x_create_phy_addr_map,
|
||||
.r_mib_cnt = ksz9477_r_mib_cnt,
|
||||
.r_mib_pkt = ksz9477_r_mib_pkt,
|
||||
.r_mib_stat64 = ksz_r_mib_stats64,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user