-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
net: mdiobus: Introduce fwnode_mdiobus_register_phy()
Introduce fwnode_mdiobus_register_phy() to register PHYs on the mdiobus. From the compatible string, identify whether the PHY is c45 and based on this create a PHY device instance which is registered on the mdiobus. Along with fwnode_mdiobus_register_phy() also introduce fwnode_find_mii_timestamper() and fwnode_mdiobus_phy_device_register() since they are needed. While at it, also use the newly introduced fwnode operation in of_mdiobus_phy_device_register(). Signed-off-by: Calvin Johnson <calvin.johnson@oss.nxp.com> Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> Acked-by: Grant Likely <grant.likely@arm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Calvin Johnson
authored and
David S. Miller
committed
Jun 11, 2021
1 parent
b9926da
commit bc1bee3
Showing
6 changed files
with
194 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
/* | ||
* fwnode helpers for the MDIO (Ethernet PHY) API | ||
* | ||
* This file provides helper functions for extracting PHY device information | ||
* out of the fwnode and using it to populate an mii_bus. | ||
*/ | ||
|
||
#include <linux/acpi.h> | ||
#include <linux/fwnode_mdio.h> | ||
#include <linux/of.h> | ||
#include <linux/phy.h> | ||
|
||
MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>"); | ||
MODULE_LICENSE("GPL"); | ||
|
||
static struct mii_timestamper * | ||
fwnode_find_mii_timestamper(struct fwnode_handle *fwnode) | ||
{ | ||
struct of_phandle_args arg; | ||
int err; | ||
|
||
if (is_acpi_node(fwnode)) | ||
return NULL; | ||
|
||
err = of_parse_phandle_with_fixed_args(to_of_node(fwnode), | ||
"timestamper", 1, 0, &arg); | ||
if (err == -ENOENT) | ||
return NULL; | ||
else if (err) | ||
return ERR_PTR(err); | ||
|
||
if (arg.args_count != 1) | ||
return ERR_PTR(-EINVAL); | ||
|
||
return register_mii_timestamper(arg.np, arg.args[0]); | ||
} | ||
|
||
int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio, | ||
struct phy_device *phy, | ||
struct fwnode_handle *child, u32 addr) | ||
{ | ||
int rc; | ||
|
||
rc = fwnode_irq_get(child, 0); | ||
if (rc == -EPROBE_DEFER) | ||
return rc; | ||
|
||
if (rc > 0) { | ||
phy->irq = rc; | ||
mdio->irq[addr] = rc; | ||
} else { | ||
phy->irq = mdio->irq[addr]; | ||
} | ||
|
||
if (fwnode_property_read_bool(child, "broken-turn-around")) | ||
mdio->phy_ignore_ta_mask |= 1 << addr; | ||
|
||
fwnode_property_read_u32(child, "reset-assert-us", | ||
&phy->mdio.reset_assert_delay); | ||
fwnode_property_read_u32(child, "reset-deassert-us", | ||
&phy->mdio.reset_deassert_delay); | ||
|
||
/* Associate the fwnode with the device structure so it | ||
* can be looked up later | ||
*/ | ||
fwnode_handle_get(child); | ||
phy->mdio.dev.fwnode = child; | ||
|
||
/* All data is now stored in the phy struct; | ||
* register it | ||
*/ | ||
rc = phy_device_register(phy); | ||
if (rc) { | ||
fwnode_handle_put(child); | ||
return rc; | ||
} | ||
|
||
dev_dbg(&mdio->dev, "registered phy %p fwnode at address %i\n", | ||
child, addr); | ||
return 0; | ||
} | ||
EXPORT_SYMBOL(fwnode_mdiobus_phy_device_register); | ||
|
||
int fwnode_mdiobus_register_phy(struct mii_bus *bus, | ||
struct fwnode_handle *child, u32 addr) | ||
{ | ||
struct mii_timestamper *mii_ts = NULL; | ||
struct phy_device *phy; | ||
bool is_c45 = false; | ||
u32 phy_id; | ||
int rc; | ||
|
||
mii_ts = fwnode_find_mii_timestamper(child); | ||
if (IS_ERR(mii_ts)) | ||
return PTR_ERR(mii_ts); | ||
|
||
rc = fwnode_property_match_string(child, "compatible", | ||
"ethernet-phy-ieee802.3-c45"); | ||
if (rc >= 0) | ||
is_c45 = true; | ||
|
||
if (is_c45 || fwnode_get_phy_id(child, &phy_id)) | ||
phy = get_phy_device(bus, addr, is_c45); | ||
else | ||
phy = phy_device_create(bus, addr, phy_id, 0, NULL); | ||
if (IS_ERR(phy)) { | ||
unregister_mii_timestamper(mii_ts); | ||
return PTR_ERR(phy); | ||
} | ||
|
||
if (is_acpi_node(child)) { | ||
phy->irq = bus->irq[addr]; | ||
|
||
/* Associate the fwnode with the device structure so it | ||
* can be looked up later. | ||
*/ | ||
phy->mdio.dev.fwnode = child; | ||
|
||
/* All data is now stored in the phy struct, so register it */ | ||
rc = phy_device_register(phy); | ||
if (rc) { | ||
phy_device_free(phy); | ||
fwnode_handle_put(phy->mdio.dev.fwnode); | ||
return rc; | ||
} | ||
} else if (is_of_node(child)) { | ||
rc = fwnode_mdiobus_phy_device_register(bus, phy, child, addr); | ||
if (rc) { | ||
unregister_mii_timestamper(mii_ts); | ||
phy_device_free(phy); | ||
return rc; | ||
} | ||
} | ||
|
||
/* phy->mii_ts may already be defined by the PHY driver. A | ||
* mii_timestamper probed via the device tree will still have | ||
* precedence. | ||
*/ | ||
if (mii_ts) | ||
phy->mii_ts = mii_ts; | ||
return 0; | ||
} | ||
EXPORT_SYMBOL(fwnode_mdiobus_register_phy); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-only */ | ||
/* | ||
* FWNODE helper for the MDIO (Ethernet PHY) API | ||
*/ | ||
|
||
#ifndef __LINUX_FWNODE_MDIO_H | ||
#define __LINUX_FWNODE_MDIO_H | ||
|
||
#include <linux/phy.h> | ||
|
||
#if IS_ENABLED(CONFIG_FWNODE_MDIO) | ||
int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio, | ||
struct phy_device *phy, | ||
struct fwnode_handle *child, u32 addr); | ||
|
||
int fwnode_mdiobus_register_phy(struct mii_bus *bus, | ||
struct fwnode_handle *child, u32 addr); | ||
|
||
#else /* CONFIG_FWNODE_MDIO */ | ||
int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio, | ||
struct phy_device *phy, | ||
struct fwnode_handle *child, u32 addr) | ||
{ | ||
return -EINVAL; | ||
} | ||
|
||
static inline int fwnode_mdiobus_register_phy(struct mii_bus *bus, | ||
struct fwnode_handle *child, | ||
u32 addr) | ||
{ | ||
return -EINVAL; | ||
} | ||
#endif | ||
|
||
#endif /* __LINUX_FWNODE_MDIO_H */ |