[PATCH 0/6] xilinx: Add support for DM_ETH_PHY

Hi,
I am sending series for adding support for DM_ETH_PHY for zynq_gem. I don't want to enable it by default now to have a time to also add support in emaclite and axi emac to be able to use shared MDIO bus across all xilinx IPs. Series also updating slg gpio driver and adding additional handling for SGMII.
Thanks, Michal
Michal Simek (1): net: zynq_gem: Use shared MDIO bus support for zynqmp
T Karthik Reddy (5): net: phy: Avoid phy gpio reset sequence if DM_ETH_PHY is enabled net: zynq_gem: Move ethernet info print statement gpio: slg7xl45106: Update gpio desc flags from DT firmware: firmware-zynqmp: Add zynqmp_pm_set_gem_config api net: zynq_gem: Add SGMII dynamic config support
drivers/firmware/firmware-zynqmp.c | 13 +++++ drivers/gpio/gpio_slg7xl45106.c | 2 + drivers/net/phy/ethernet_id.c | 45 +++++++++------- drivers/net/zynq_gem.c | 86 +++++++++++++++++++++++++----- include/zynqmp_firmware.h | 7 +++ 5 files changed, 121 insertions(+), 32 deletions(-)

CONFIG_ETH_PHY enables support to utilize generic ethernet phy framework. Though if ethernet PHY node is in other ethernet node, it will use shared MDIO to access the PHY of other ethernet.
Signed-off-by: Michal Simek michal.simek@xilinx.com Signed-off-by: T Karthik Reddy t.karthik.reddy@xilinx.com ---
drivers/net/zynq_gem.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 3118d1472669..168aabbdd006 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -33,6 +33,7 @@ #include <linux/bitops.h> #include <linux/err.h> #include <linux/errno.h> +#include <eth_phy.h>
/* Bit/mask specification */ #define ZYNQ_GEM_PHYMNTNC_OP_MASK 0x40020000 /* operation mask bits */ @@ -321,6 +322,9 @@ static int zynq_phy_init(struct udevice *dev) /* Enable only MDIO bus */ writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, ®s_mdio->nwctrl);
+ if (IS_ENABLED(CONFIG_DM_ETH_PHY)) + priv->phyaddr = eth_phy_get_addr(dev); + priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface); if (!priv->phydev) @@ -771,14 +775,22 @@ static int zynq_gem_probe(struct udevice *dev) } }
- priv->bus = mdio_alloc(); - priv->bus->read = zynq_gem_miiphy_read; - priv->bus->write = zynq_gem_miiphy_write; - priv->bus->priv = priv; + if (IS_ENABLED(CONFIG_DM_ETH_PHY)) + priv->bus = eth_phy_get_mdio_bus(dev);
- ret = mdio_register_seq(priv->bus, dev_seq(dev)); - if (ret) - goto err2; + if (!priv->bus) { + priv->bus = mdio_alloc(); + priv->bus->read = zynq_gem_miiphy_read; + priv->bus->write = zynq_gem_miiphy_write; + priv->bus->priv = priv; + + ret = mdio_register_seq(priv->bus, dev_seq(dev)); + if (ret) + goto err2; + } + + if (IS_ENABLED(CONFIG_DM_ETH_PHY)) + eth_phy_set_mdio_bus(dev, priv->bus);
ret = zynq_phy_init(dev); if (ret) @@ -841,8 +853,10 @@ static int zynq_gem_of_to_plat(struct udevice *dev) ofnode parent;
debug("phy-handle does exist %s\n", dev->name); - priv->phyaddr = ofnode_read_u32_default(phandle_args.node, - "reg", -1); + if (!(IS_ENABLED(CONFIG_DM_ETH_PHY))) + priv->phyaddr = ofnode_read_u32_default + (phandle_args.node, "reg", -1); + priv->phy_of_node = phandle_args.node; priv->max_speed = ofnode_read_u32_default(phandle_args.node, "max-speed",

From: T Karthik Reddy t.karthik.reddy@xilinx.com
If DM_ETH_PHY config is enabled PHY gpio reset is taken care by the eth-phy-uclass driver, so use the PHY gpio reset functionality from ethernet_id file when this config is disabled to reset the PHY. Use debug() print instead of dev_err() to avoid warning incase if phy-id compatible string is not present.
Signed-off-by: T Karthik Reddy t.karthik.reddy@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
drivers/net/phy/ethernet_id.c | 45 ++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 19 deletions(-)
diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c index 44abc5bfb301..1a78a751ede3 100644 --- a/drivers/net/phy/ethernet_id.c +++ b/drivers/net/phy/ethernet_id.c @@ -33,31 +33,38 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
ret = ofnode_read_eth_phy_id(node, &vendor, &device); if (ret) { - dev_err(dev, "Failed to read eth PHY id, err: %d\n", ret); + debug("Failed to read eth PHY id, err: %d\n", ret); return NULL; }
- ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio, - GPIOD_ACTIVE_LOW); - if (!ret) { - assert = ofnode_read_u32_default(node, "reset-assert-us", 0); - deassert = ofnode_read_u32_default(node, - "reset-deassert-us", 0); - ret = dm_gpio_set_value(&gpio, 1); - if (ret) { - dev_err(dev, "Failed assert gpio, err: %d\n", ret); - return NULL; - } + if (!IS_ENABLED(CONFIG_DM_ETH_PHY)) { + ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio, + GPIOD_ACTIVE_LOW); + if (!ret) { + assert = ofnode_read_u32_default(node, + "reset-assert-us", 0); + deassert = ofnode_read_u32_default(node, + "reset-deassert-us", + 0); + ret = dm_gpio_set_value(&gpio, 1); + if (ret) { + dev_err(dev, + "Failed assert gpio, err: %d\n", ret); + return NULL; + }
- udelay(assert); + udelay(assert);
- ret = dm_gpio_set_value(&gpio, 0); - if (ret) { - dev_err(dev, "Failed deassert gpio, err: %d\n", ret); - return NULL; - } + ret = dm_gpio_set_value(&gpio, 0); + if (ret) { + dev_err(dev, + "Failed deassert gpio, err: %d\n", + ret); + return NULL; + }
- udelay(deassert); + udelay(deassert); + } }
id = vendor << 16 | device;

From: T Karthik Reddy t.karthik.reddy@xilinx.com
As we are not reading the PHY address in case of CONFIG_ETH_PHY in plat function, phy address always prints as -1. So move the ethernet info print statement to probe function, to display proper phy address.
Signed-off-by: T Karthik Reddy t.karthik.reddy@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
drivers/net/zynq_gem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 168aabbdd006..07de1bf0a40e 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -802,6 +802,10 @@ static int zynq_gem_probe(struct udevice *dev) return ret; }
+ printf("\nZYNQ GEM: %lx, mdio bus %lx, phyaddr %d, interface %s\n", + (ulong)priv->iobase, (ulong)priv->mdiobase, priv->phydev->addr, + phy_string_for_interface(priv->interface)); + return ret;
err3: @@ -884,10 +888,6 @@ static int zynq_gem_of_to_plat(struct udevice *dev)
priv->int_pcs = dev_read_bool(dev, "is-internal-pcspma");
- printf("\nZYNQ GEM: %lx, mdio bus %lx, phyaddr %d, interface %s\n", - (ulong)priv->iobase, (ulong)priv->mdiobase, priv->phyaddr, - phy_string_for_interface(priv->interface)); - priv->clk_en_info = dev_get_driver_data(dev);
return 0;

From: T Karthik Reddy t.karthik.reddy@xilinx.com
In current slg7xl45106 gpio driver xlate() function we are not updating gpio flags from DT. Read the given flag from DT and update the gpio desc flags variable with required gpio direction state.
Signed-off-by: T Karthik Reddy t.karthik.reddy@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
drivers/gpio/gpio_slg7xl45106.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpio/gpio_slg7xl45106.c b/drivers/gpio/gpio_slg7xl45106.c index 2cbf7488ad62..4ad06c18b4bd 100644 --- a/drivers/gpio/gpio_slg7xl45106.c +++ b/drivers/gpio/gpio_slg7xl45106.c @@ -11,6 +11,7 @@ #include <asm/gpio.h> #include <dm.h> #include <i2c.h> +#include <dt-bindings/gpio/gpio.h> #include <asm/arch/hardware.h>
#define SLG7XL45106_REG 0xdb @@ -26,6 +27,7 @@ static int slg7xl45106_i2c_gpo_xlate(struct udevice *dev, struct ofnode_phandle_args *args) { desc->offset = (unsigned int)args->args[0]; + desc->flags = (args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0);
return 0; }

From: T Karthik Reddy t.karthik.reddy@xilinx.com
Add zynqmp_pm_set_gem_config() api to configure GEM secure registers.
Signed-off-by: T Karthik Reddy t.karthik.reddy@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
drivers/firmware/firmware-zynqmp.c | 13 +++++++++++++ include/zynqmp_firmware.h | 7 +++++++ 2 files changed, 20 insertions(+)
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 78da5abc5d3e..0f0d2b07c005 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -140,6 +140,19 @@ unsigned int zynqmp_firmware_version(void) return pm_api_version; };
+int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, u32 value) +{ + int ret; + + ret = xilinx_pm_request(PM_IOCTL, node, IOCTL_SET_GEM_CONFIG, + config, value, NULL); + if (ret) + printf("%s: node %d: set_gem_config %d failed\n", + __func__, node, config); + + return ret; +} + int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value) { int ret; diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index f577008736d9..76ec2141ff6a 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -408,6 +408,11 @@ enum pm_sd_config_type { SD_CONFIG_FIXED = 4, /* To set fixed config registers */ };
+enum pm_gem_config_type { + GEM_CONFIG_SGMII_MODE = 1, /* To set GEM_SGMII_MODE in GEM_CLK_CTRL */ + GEM_CONFIG_FIXED = 2, /* To set fixed config registers */ +}; + #define PM_SIP_SVC 0xc2000000
#define ZYNQMP_PM_VERSION_MAJOR 1 @@ -439,6 +444,8 @@ void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size); int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 *ret_payload); int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value); +int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, + u32 value); int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id);
/* Type of Config Object */

From: T Karthik Reddy t.karthik.reddy@xilinx.com
Add support for SGMII dynamic configuration which will takes care of configuring SGMII in the GEM secure (GEM_CLK_CTRL) configuration register.
Signed-off-by: T Karthik Reddy t.karthik.reddy@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
drivers/net/zynq_gem.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 07de1bf0a40e..4c83ccc1dfbc 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -34,6 +34,7 @@ #include <linux/err.h> #include <linux/errno.h> #include <eth_phy.h> +#include <zynqmp_firmware.h>
/* Bit/mask specification */ #define ZYNQ_GEM_PHYMNTNC_OP_MASK 0x40020000 /* operation mask bits */ @@ -714,6 +715,40 @@ static int zynq_gem_reset_init(struct udevice *dev) return 0; }
+static int gem_zynqmp_set_dynamic_config(struct udevice *dev) +{ + u32 pm_info[2]; + int ret; + + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) { + if (!zynqmp_pm_is_function_supported(PM_IOCTL, + IOCTL_SET_GEM_CONFIG)) { + ret = ofnode_read_u32_array(dev_ofnode(dev), + "power-domains", + pm_info, + ARRAY_SIZE(pm_info)); + if (ret) { + dev_err(dev, + "Failed to read power-domains info\n"); + return ret; + } + + ret = zynqmp_pm_set_gem_config(pm_info[1], + GEM_CONFIG_FIXED, 0); + if (ret) + return ret; + + ret = zynqmp_pm_set_gem_config(pm_info[1], + GEM_CONFIG_SGMII_MODE, + 1); + if (ret) + return ret; + } + } + + return 0; +} + static int zynq_gem_probe(struct udevice *dev) { void *bd_space; @@ -797,6 +832,17 @@ static int zynq_gem_probe(struct udevice *dev) goto err3;
if (priv->interface == PHY_INTERFACE_MODE_SGMII && phy.dev) { + if (IS_ENABLED(CONFIG_DM_ETH_PHY)) { + if (device_is_compatible(dev, "cdns,zynqmp-gem")) { + ret = gem_zynqmp_set_dynamic_config(dev); + if (ret) { + dev_err + (dev, + "Failed to set gem dynamic config\n"); + return ret; + } + } + } ret = generic_phy_power_on(&phy); if (ret) return ret;

st 30. 3. 2022 v 11:08 odesÃlatel Michal Simek michal.simek@xilinx.com napsal:
Hi,
I am sending series for adding support for DM_ETH_PHY for zynq_gem. I don't want to enable it by default now to have a time to also add support in emaclite and axi emac to be able to use shared MDIO bus across all xilinx IPs. Series also updating slg gpio driver and adding additional handling for SGMII.
Thanks, Michal
Michal Simek (1): net: zynq_gem: Use shared MDIO bus support for zynqmp
T Karthik Reddy (5): net: phy: Avoid phy gpio reset sequence if DM_ETH_PHY is enabled net: zynq_gem: Move ethernet info print statement gpio: slg7xl45106: Update gpio desc flags from DT firmware: firmware-zynqmp: Add zynqmp_pm_set_gem_config api net: zynq_gem: Add SGMII dynamic config support
drivers/firmware/firmware-zynqmp.c | 13 +++++ drivers/gpio/gpio_slg7xl45106.c | 2 + drivers/net/phy/ethernet_id.c | 45 +++++++++------- drivers/net/zynq_gem.c | 86 +++++++++++++++++++++++++----- include/zynqmp_firmware.h | 7 +++ 5 files changed, 121 insertions(+), 32 deletions(-)
-- 2.35.1
Applied. M
participants (2)
-
Michal Simek
-
Michal Simek