Commit 8fa7b9b6 authored by Russell King's avatar Russell King Committed by David S. Miller

phylink: convert to fwnode

Convert phylink to fwnode, switching phylink_create() from taking a
device_node to taking a fwnode_handle. This will allow other firmware
systems to take advantage of sfp/phylink support.
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c19bb000
...@@ -142,59 +142,64 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported, ...@@ -142,59 +142,64 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported,
return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
} }
static int phylink_parse_fixedlink(struct phylink *pl, struct device_node *np) static int phylink_parse_fixedlink(struct phylink *pl,
struct fwnode_handle *fwnode)
{ {
struct device_node *fixed_node; struct fwnode_handle *fixed_node;
const struct phy_setting *s; const struct phy_setting *s;
struct gpio_desc *desc; struct gpio_desc *desc;
const __be32 *fixed_prop;
u32 speed; u32 speed;
int ret, len; int ret;
fixed_node = of_get_child_by_name(np, "fixed-link"); fixed_node = fwnode_get_named_child_node(fwnode, "fixed-link");
if (fixed_node) { if (fixed_node) {
ret = of_property_read_u32(fixed_node, "speed", &speed); ret = fwnode_property_read_u32(fixed_node, "speed", &speed);
pl->link_config.speed = speed; pl->link_config.speed = speed;
pl->link_config.duplex = DUPLEX_HALF; pl->link_config.duplex = DUPLEX_HALF;
if (of_property_read_bool(fixed_node, "full-duplex")) if (fwnode_property_read_bool(fixed_node, "full-duplex"))
pl->link_config.duplex = DUPLEX_FULL; pl->link_config.duplex = DUPLEX_FULL;
/* We treat the "pause" and "asym-pause" terminology as /* We treat the "pause" and "asym-pause" terminology as
* defining the link partner's ability. */ * defining the link partner's ability. */
if (of_property_read_bool(fixed_node, "pause")) if (fwnode_property_read_bool(fixed_node, "pause"))
pl->link_config.pause |= MLO_PAUSE_SYM; pl->link_config.pause |= MLO_PAUSE_SYM;
if (of_property_read_bool(fixed_node, "asym-pause")) if (fwnode_property_read_bool(fixed_node, "asym-pause"))
pl->link_config.pause |= MLO_PAUSE_ASYM; pl->link_config.pause |= MLO_PAUSE_ASYM;
if (ret == 0) { if (ret == 0) {
desc = fwnode_get_named_gpiod(&fixed_node->fwnode, desc = fwnode_get_named_gpiod(fixed_node, "link-gpios",
"link-gpios", 0, 0, GPIOD_IN, "?");
GPIOD_IN, "?");
if (!IS_ERR(desc)) if (!IS_ERR(desc))
pl->link_gpio = desc; pl->link_gpio = desc;
else if (desc == ERR_PTR(-EPROBE_DEFER)) else if (desc == ERR_PTR(-EPROBE_DEFER))
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
} }
of_node_put(fixed_node); fwnode_handle_put(fixed_node);
if (ret) if (ret)
return ret; return ret;
} else { } else {
fixed_prop = of_get_property(np, "fixed-link", &len); u32 prop[5];
if (!fixed_prop) {
ret = fwnode_property_read_u32_array(fwnode, "fixed-link",
NULL, 0);
if (ret != ARRAY_SIZE(prop)) {
netdev_err(pl->netdev, "broken fixed-link?\n"); netdev_err(pl->netdev, "broken fixed-link?\n");
return -EINVAL; return -EINVAL;
} }
if (len == 5 * sizeof(*fixed_prop)) {
pl->link_config.duplex = be32_to_cpu(fixed_prop[1]) ? ret = fwnode_property_read_u32_array(fwnode, "fixed-link",
prop, ARRAY_SIZE(prop));
if (!ret) {
pl->link_config.duplex = prop[1] ?
DUPLEX_FULL : DUPLEX_HALF; DUPLEX_FULL : DUPLEX_HALF;
pl->link_config.speed = be32_to_cpu(fixed_prop[2]); pl->link_config.speed = prop[2];
if (be32_to_cpu(fixed_prop[3])) if (prop[3])
pl->link_config.pause |= MLO_PAUSE_SYM; pl->link_config.pause |= MLO_PAUSE_SYM;
if (be32_to_cpu(fixed_prop[4])) if (prop[4])
pl->link_config.pause |= MLO_PAUSE_ASYM; pl->link_config.pause |= MLO_PAUSE_ASYM;
} }
} }
...@@ -230,17 +235,17 @@ static int phylink_parse_fixedlink(struct phylink *pl, struct device_node *np) ...@@ -230,17 +235,17 @@ static int phylink_parse_fixedlink(struct phylink *pl, struct device_node *np)
return 0; return 0;
} }
static int phylink_parse_mode(struct phylink *pl, struct device_node *np) static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
{ {
struct device_node *dn; struct fwnode_handle *dn;
const char *managed; const char *managed;
dn = of_get_child_by_name(np, "fixed-link"); dn = fwnode_get_named_child_node(fwnode, "fixed-link");
if (dn || of_find_property(np, "fixed-link", NULL)) if (dn || fwnode_property_present(fwnode, "fixed-link"))
pl->link_an_mode = MLO_AN_FIXED; pl->link_an_mode = MLO_AN_FIXED;
of_node_put(dn); fwnode_handle_put(dn);
if (of_property_read_string(np, "managed", &managed) == 0 && if (fwnode_property_read_string(fwnode, "managed", &managed) == 0 &&
strcmp(managed, "in-band-status") == 0) { strcmp(managed, "in-band-status") == 0) {
if (pl->link_an_mode == MLO_AN_FIXED) { if (pl->link_an_mode == MLO_AN_FIXED) {
netdev_err(pl->netdev, netdev_err(pl->netdev,
...@@ -491,16 +496,24 @@ static void phylink_run_resolve(struct phylink *pl) ...@@ -491,16 +496,24 @@ static void phylink_run_resolve(struct phylink *pl)
static const struct sfp_upstream_ops sfp_phylink_ops; static const struct sfp_upstream_ops sfp_phylink_ops;
static int phylink_register_sfp(struct phylink *pl, struct device_node *np) static int phylink_register_sfp(struct phylink *pl,
struct fwnode_handle *fwnode)
{ {
struct device_node *sfp_np; struct fwnode_reference_args ref;
int ret;
sfp_np = of_parse_phandle(np, "sfp", 0); ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL,
if (!sfp_np) 0, 0, &ref);
return 0; if (ret < 0) {
if (ret == -ENOENT)
return 0;
netdev_err(pl->netdev, "unable to parse \"sfp\" node: %d\n",
ret);
return ret;
}
pl->sfp_bus = sfp_register_upstream(of_fwnode_handle(sfp_np), pl->sfp_bus = sfp_register_upstream(ref.fwnode, pl->netdev, pl,
pl->netdev, pl,
&sfp_phylink_ops); &sfp_phylink_ops);
if (!pl->sfp_bus) if (!pl->sfp_bus)
return -ENOMEM; return -ENOMEM;
...@@ -511,7 +524,8 @@ static int phylink_register_sfp(struct phylink *pl, struct device_node *np) ...@@ -511,7 +524,8 @@ static int phylink_register_sfp(struct phylink *pl, struct device_node *np)
/** /**
* phylink_create() - create a phylink instance * phylink_create() - create a phylink instance
* @ndev: a pointer to the &struct net_device * @ndev: a pointer to the &struct net_device
* @np: a pointer to a &struct device_node describing the network interface * @fwnode: a pointer to a &struct fwnode_handle describing the network
* interface
* @iface: the desired link mode defined by &typedef phy_interface_t * @iface: the desired link mode defined by &typedef phy_interface_t
* @ops: a pointer to a &struct phylink_mac_ops for the MAC. * @ops: a pointer to a &struct phylink_mac_ops for the MAC.
* *
...@@ -521,7 +535,8 @@ static int phylink_register_sfp(struct phylink *pl, struct device_node *np) ...@@ -521,7 +535,8 @@ static int phylink_register_sfp(struct phylink *pl, struct device_node *np)
* Returns a pointer to a &struct phylink, or an error-pointer value. Users * Returns a pointer to a &struct phylink, or an error-pointer value. Users
* must use IS_ERR() to check for errors from this function. * must use IS_ERR() to check for errors from this function.
*/ */
struct phylink *phylink_create(struct net_device *ndev, struct device_node *np, struct phylink *phylink_create(struct net_device *ndev,
struct fwnode_handle *fwnode,
phy_interface_t iface, phy_interface_t iface,
const struct phylink_mac_ops *ops) const struct phylink_mac_ops *ops)
{ {
...@@ -549,21 +564,21 @@ struct phylink *phylink_create(struct net_device *ndev, struct device_node *np, ...@@ -549,21 +564,21 @@ struct phylink *phylink_create(struct net_device *ndev, struct device_node *np,
linkmode_copy(pl->link_config.advertising, pl->supported); linkmode_copy(pl->link_config.advertising, pl->supported);
phylink_validate(pl, pl->supported, &pl->link_config); phylink_validate(pl, pl->supported, &pl->link_config);
ret = phylink_parse_mode(pl, np); ret = phylink_parse_mode(pl, fwnode);
if (ret < 0) { if (ret < 0) {
kfree(pl); kfree(pl);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
if (pl->link_an_mode == MLO_AN_FIXED) { if (pl->link_an_mode == MLO_AN_FIXED) {
ret = phylink_parse_fixedlink(pl, np); ret = phylink_parse_fixedlink(pl, fwnode);
if (ret < 0) { if (ret < 0) {
kfree(pl); kfree(pl);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
} }
ret = phylink_register_sfp(pl, np); ret = phylink_register_sfp(pl, fwnode);
if (ret < 0) { if (ret < 0) {
kfree(pl); kfree(pl);
return ERR_PTR(ret); return ERR_PTR(ret);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
struct device_node; struct device_node;
struct ethtool_cmd; struct ethtool_cmd;
struct fwnode_handle;
struct net_device; struct net_device;
enum { enum {
...@@ -182,7 +183,7 @@ void mac_link_up(struct net_device *ndev, unsigned int mode, ...@@ -182,7 +183,7 @@ void mac_link_up(struct net_device *ndev, unsigned int mode,
struct phy_device *phy); struct phy_device *phy);
#endif #endif
struct phylink *phylink_create(struct net_device *, struct device_node *, struct phylink *phylink_create(struct net_device *, struct fwnode_handle *,
phy_interface_t iface, const struct phylink_mac_ops *ops); phy_interface_t iface, const struct phylink_mac_ops *ops);
void phylink_destroy(struct phylink *); void phylink_destroy(struct phylink *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment