This patch adds support for having a "fixed-link" to some other MAC (like some embedded switch-device). For this purpose we introduce a new phy-driver, called "Fixed PHY". Fixed PHY works only with CONFIG_DM_ETH enabled, since the fixed-link is described with a subnode below ethernet interface. Most ethernet drivers (unfortunately not all are following same scheme for searching/attaching phys) are calling "phy_connect(...)" for getting a phy-device. At this point we link in, we search here for a subnode called "fixed- link", once found we start phy_device_create(...) with the special phy- id PHY_FIXED_ID (0xa5a55a5a). During init the "Fixed PHY" driver has registered with this id and now gets probed, during probe we get all the details about fixed-link out of dts, later on the phy reports this values. Signed-off-by: Hannes Schmelzer <hannes.schmelzer@br-automation.com> Signed-off-by: Hannes Schmelzer <oe5hpm@oevsv.at> Acked-by: Joe Hershberger <joe.hershberger@ni.com> Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>master
parent
f8e57c650d
commit
db40c1aa1c
@ -0,0 +1,30 @@ |
|||||||
|
Fixed link Device Tree binding |
||||||
|
------------------------------ |
||||||
|
|
||||||
|
Some Ethernet MACs have a "fixed link", and are not connected to a |
||||||
|
normal MDIO-managed PHY device. For those situations, a Device Tree |
||||||
|
binding allows to describe a "fixed link". |
||||||
|
|
||||||
|
Such a fixed link situation is described by creating a 'fixed-link' |
||||||
|
sub-node of the Ethernet MAC device node, with the following |
||||||
|
properties: |
||||||
|
|
||||||
|
* 'speed' (integer, mandatory), to indicate the link speed. Accepted |
||||||
|
values are 10, 100 and 1000 |
||||||
|
* 'full-duplex' (boolean, optional), to indicate that full duplex is |
||||||
|
used. When absent, half duplex is assumed. |
||||||
|
* 'pause' (boolean, optional), to indicate that pause should be |
||||||
|
enabled. |
||||||
|
* 'asym-pause' (boolean, optional), to indicate that asym_pause should |
||||||
|
be enabled. |
||||||
|
|
||||||
|
Examples: |
||||||
|
|
||||||
|
ethernet@0 { |
||||||
|
... |
||||||
|
fixed-link { |
||||||
|
speed = <1000>; |
||||||
|
full-duplex; |
||||||
|
}; |
||||||
|
... |
||||||
|
}; |
@ -0,0 +1,82 @@ |
|||||||
|
/*
|
||||||
|
* Fixed-Link phy |
||||||
|
* |
||||||
|
* Copyright 2017 Bernecker & Rainer Industrieelektronik GmbH |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: GPL-2.0+ |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <config.h> |
||||||
|
#include <common.h> |
||||||
|
#include <phy.h> |
||||||
|
#include <dm.h> |
||||||
|
#include <fdt_support.h> |
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR; |
||||||
|
|
||||||
|
int fixedphy_probe(struct phy_device *phydev) |
||||||
|
{ |
||||||
|
struct fixed_link *priv; |
||||||
|
int ofnode = phydev->addr; |
||||||
|
u32 val; |
||||||
|
|
||||||
|
/* check for mandatory properties within fixed-link node */ |
||||||
|
val = fdt_getprop_u32_default_node(gd->fdt_blob, |
||||||
|
ofnode, 0, "speed", 0); |
||||||
|
if (val != SPEED_10 && val != SPEED_100 && val != SPEED_1000) { |
||||||
|
printf("ERROR: no/invalid speed given in fixed-link node!"); |
||||||
|
return -EINVAL; |
||||||
|
} |
||||||
|
|
||||||
|
priv = malloc(sizeof(*priv)); |
||||||
|
if (!priv) |
||||||
|
return -ENOMEM; |
||||||
|
memset(priv, 0, sizeof(*priv)); |
||||||
|
|
||||||
|
phydev->priv = priv; |
||||||
|
phydev->addr = 0; |
||||||
|
|
||||||
|
priv->link_speed = val; |
||||||
|
priv->duplex = fdtdec_get_bool(gd->fdt_blob, ofnode, "full-duplex"); |
||||||
|
priv->pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "pause"); |
||||||
|
priv->asym_pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "asym-pause"); |
||||||
|
|
||||||
|
/* fixed-link phy must not be reset by core phy code */ |
||||||
|
phydev->flags |= PHY_FLAG_BROKEN_RESET; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int fixedphy_startup(struct phy_device *phydev) |
||||||
|
{ |
||||||
|
struct fixed_link *priv = phydev->priv; |
||||||
|
|
||||||
|
phydev->asym_pause = priv->asym_pause; |
||||||
|
phydev->pause = priv->pause; |
||||||
|
phydev->duplex = priv->duplex; |
||||||
|
phydev->speed = priv->link_speed; |
||||||
|
phydev->link = 1; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int fixedphy_shutdown(struct phy_device *phydev) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static struct phy_driver fixedphy_driver = { |
||||||
|
.uid = PHY_FIXED_ID, |
||||||
|
.mask = 0xffffffff, |
||||||
|
.name = "Fixed PHY", |
||||||
|
.features = PHY_GBIT_FEATURES | SUPPORTED_MII, |
||||||
|
.probe = fixedphy_probe, |
||||||
|
.startup = fixedphy_startup, |
||||||
|
.shutdown = fixedphy_shutdown, |
||||||
|
}; |
||||||
|
|
||||||
|
int phy_fixed_init(void) |
||||||
|
{ |
||||||
|
phy_register(&fixedphy_driver); |
||||||
|
return 0; |
||||||
|
} |
Loading…
Reference in new issue