summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorCamelia Groza <camelia.groza@nxp.com>2022-05-24 21:12:32 +0300
committerXiaobo Xie <xiaobo.xie@nxp.com>2022-05-30 13:06:56 +0200
commit9afbdf3713a9cdf15eece57bfc97d8beb62af0ae (patch)
tree6a33eb7698353023d08a8e155e3163f2f6d00ddf /drivers
parentf405a4f65855b384ad5b7cd3eff1ff815826ffa8 (diff)
net: phy: fixed_phy: add fixed PHY ACPI support
Add the fwnode_fixed_phy_register() call. The call is similar to the existing fixed_phy_register(). Signed-off-by: Vikas Singh <vikas.singh@puresoftware.com> Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/fixed_phy.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index c65fb5f5d2dc..8e834fcf72d9 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -6,6 +6,7 @@
* Anton Vorontsov <avorontsov@ru.mvista.com>
*
* Copyright (c) 2006-2007 MontaVista Software, Inc.
+ * Copyright (c) 2020 Puresoftware Ltd.
*/
#include <linux/kernel.h>
@@ -223,6 +224,78 @@ static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np)
}
#endif
+struct phy_device *fwnode_fixed_phy_register(struct fwnode_handle *fwnode_np,
+ struct fixed_phy_status *status)
+{
+ struct fixed_mdio_bus *fmb = &platform_fmb;
+ struct phy_device *phy;
+ int phy_addr;
+ int ret;
+
+ if (!fmb->mii_bus || fmb->mii_bus->state != MDIOBUS_REGISTERED)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ phy_addr = ida_simple_get(&phy_fixed_ida, 0, PHY_MAX_ADDR, GFP_KERNEL);
+ if (phy_addr < 0)
+ return ERR_PTR(phy_addr);
+
+ ret = fixed_phy_add_gpiod(PHY_POLL, phy_addr, status, NULL);
+ if (ret < 0) {
+ ida_simple_remove(&phy_fixed_ida, phy_addr);
+ return ERR_PTR(ret);
+ }
+
+ phy = get_phy_device(fmb->mii_bus, phy_addr, false);
+ if (IS_ERR(phy)) {
+ fixed_phy_del(phy_addr);
+ return ERR_PTR(-EINVAL);
+ }
+
+ phy->link = status->link;
+ if (status->link) {
+ phy->speed = status->speed;
+ phy->duplex = status->duplex;
+ phy->pause = status->pause;
+ phy->asym_pause = status->asym_pause;
+ }
+
+ phy->mdio.dev.fwnode = fwnode_np;
+ phy->is_pseudo_fixed_link = true;
+
+ switch (status->speed) {
+ case SPEED_1000:
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+ phy->supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ phy->supported);
+ fallthrough;
+ case SPEED_100:
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ phy->supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ phy->supported);
+ fallthrough;
+ case SPEED_10:
+ default:
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+ phy->supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+ phy->supported);
+ }
+
+ phy_advertise_supported(phy);
+
+ ret = phy_device_register(phy);
+ if (ret) {
+ phy_device_free(phy);
+ fixed_phy_del(phy_addr);
+ return ERR_PTR(ret);
+ }
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(fwnode_fixed_phy_register);
+
static struct phy_device *__fixed_phy_register(unsigned int irq,
struct fixed_phy_status *status,
struct device_node *np,