summaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/microchip/ksz_common.c
diff options
context:
space:
mode:
authorArun Ramadoss <arun.ramadoss@microchip.com>2022-07-24 14:58:20 +0530
committerDavid S. Miller <davem@davemloft.net>2022-07-27 09:39:17 +0100
commitb19ac41faa3f9602f245d1ab679f7fa96d388320 (patch)
tree8bc5e40bbaa39f091452ff52ee2faeadb9a6f3bf /drivers/net/dsa/microchip/ksz_common.c
parentdc1c596edba5e656256c2d6e6922246c7803f2de (diff)
downloadlinux-b19ac41faa3f9602f245d1ab679f7fa96d388320.tar.bz2
net: dsa: microchip: apply rgmii tx and rx delay in phylink mac config
This patch read the rgmii tx and rx delay from device tree and stored it in the ksz_port. It applies the rgmii delay to the xmii tune adjust register based on the interface selected in phylink mac config. There are two rgmii port in LAN937x and value to be loaded in the register vary depends on the port selected. Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/microchip/ksz_common.c')
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 39b83b4d02ed..237dec7c6e3c 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -223,6 +223,7 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
.mirror_del = ksz9477_port_mirror_del,
.get_caps = lan937x_phylink_get_caps,
.phylink_mac_config = lan937x_phylink_mac_config,
+ .setup_rgmii_delay = lan937x_setup_rgmii_delay,
.fdb_dump = ksz9477_fdb_dump,
.fdb_add = ksz9477_fdb_add,
.fdb_del = ksz9477_fdb_del,
@@ -1411,12 +1412,14 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface)
{
const u8 *bitval = dev->info->xmii_ctrl1;
+ struct ksz_port *p = &dev->ports[port];
const u16 *regs = dev->info->regs;
u8 data8;
ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
- data8 &= ~P_MII_SEL_M;
+ data8 &= ~(P_MII_SEL_M | P_RGMII_ID_IG_ENABLE |
+ P_RGMII_ID_EG_ENABLE);
switch (interface) {
case PHY_INTERFACE_MODE_MII:
@@ -1440,6 +1443,12 @@ void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface)
return;
}
+ if (p->rgmii_tx_val)
+ data8 |= P_RGMII_ID_EG_ENABLE;
+
+ if (p->rgmii_rx_val)
+ data8 |= P_RGMII_ID_IG_ENABLE;
+
/* Write the updated value */
ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);
}
@@ -1452,6 +1461,9 @@ static void ksz_phylink_mac_config(struct dsa_switch *ds, int port,
if (dev->dev_ops->phylink_mac_config)
dev->dev_ops->phylink_mac_config(dev, port, mode, state);
+
+ if (dev->dev_ops->setup_rgmii_delay)
+ dev->dev_ops->setup_rgmii_delay(dev, port);
}
bool ksz_get_gbit(struct ksz_device *dev, int port)
@@ -1701,6 +1713,43 @@ struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
}
EXPORT_SYMBOL(ksz_switch_alloc);
+static void ksz_parse_rgmii_delay(struct ksz_device *dev, int port_num,
+ struct device_node *port_dn)
+{
+ phy_interface_t phy_mode = dev->ports[port_num].interface;
+ int rx_delay = -1, tx_delay = -1;
+
+ if (!phy_interface_mode_is_rgmii(phy_mode))
+ return;
+
+ of_property_read_u32(port_dn, "rx-internal-delay-ps", &rx_delay);
+ of_property_read_u32(port_dn, "tx-internal-delay-ps", &tx_delay);
+
+ if (rx_delay == -1 && tx_delay == -1) {
+ dev_warn(dev->dev,
+ "Port %d interpreting RGMII delay settings based on \"phy-mode\" property, "
+ "please update device tree to specify \"rx-internal-delay-ps\" and "
+ "\"tx-internal-delay-ps\"",
+ port_num);
+
+ if (phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
+ phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
+ rx_delay = 2000;
+
+ if (phy_mode == PHY_INTERFACE_MODE_RGMII_TXID ||
+ phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
+ tx_delay = 2000;
+ }
+
+ if (rx_delay < 0)
+ rx_delay = 0;
+ if (tx_delay < 0)
+ tx_delay = 0;
+
+ dev->ports[port_num].rgmii_rx_val = rx_delay;
+ dev->ports[port_num].rgmii_tx_val = tx_delay;
+}
+
int ksz_switch_register(struct ksz_device *dev)
{
const struct ksz_chip_data *info;
@@ -1798,6 +1847,8 @@ int ksz_switch_register(struct ksz_device *dev)
}
of_get_phy_mode(port,
&dev->ports[port_num].interface);
+
+ ksz_parse_rgmii_delay(dev, port_num, port);
}
of_node_put(ports);
}