diff options
author | Arun Ramadoss <arun.ramadoss@microchip.com> | 2022-07-24 14:58:20 +0530 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-07-27 09:39:17 +0100 |
commit | b19ac41faa3f9602f245d1ab679f7fa96d388320 (patch) | |
tree | 8bc5e40bbaa39f091452ff52ee2faeadb9a6f3bf /drivers/net/dsa/microchip/ksz_common.c | |
parent | dc1c596edba5e656256c2d6e6922246c7803f2de (diff) | |
download | linux-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.c | 53 |
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); } |