From: Wang Dongsheng <hidden> Date: 2018-09-17 08:53:27
The emac include MDIO controller, and the motherboard has more than one
PHY connected to an MDIO bus. So share the shared mii_bus for others MAC
device that not has MDIO bus connected.
Tested: QDF2400 (ACPI), buildin/insmod/rmmod
V2:
- Separate patch.
- bindings: s/Since QDF2400 emac/Since emac/
Wang Dongsheng (4):
net: qcom/emac: split phy_config to mdio bus create and get phy device
dt-bindings: net: qcom: Add binding for shared mdio bus
net: qcom/emac: add of shared mdio bus support
net: qcom/emac: add acpi shared mdio bus support
.../devicetree/bindings/net/qcom-emac.txt | 4 +
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 207 ++++++++++++++----
drivers/net/ethernet/qualcomm/emac/emac.c | 8 +-
3 files changed, 175 insertions(+), 44 deletions(-)
--
2.18.0
From: Wang Dongsheng <hidden> Date: 2018-09-17 08:53:29
This property copy from "ibm,emac.txt" to describe a shared MIDO bus.
Since emac include MDIO, so If the motherboard has more than one PHY
connected to an MDIO bus, this property will point to the MAC device
that has the MDIO bus.
Signed-off-by: Wang Dongsheng <redacted>
---
V2: s/Since QDF2400 emac/Since emac/
---
Documentation/devicetree/bindings/net/qcom-emac.txt | 4 ++++
1 file changed, 4 insertions(+)
From: Wang Dongsheng <hidden> Date: 2018-09-17 14:20:11
This patch separate emac_mdio_bus_create and emac_get_phydev from
emac_phy_config, and do some codes clean.
Signed-off-by: Wang Dongsheng <redacted>
---
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 99 +++++++++++--------
1 file changed, 57 insertions(+), 42 deletions(-)
@@ -96,15 +96,14 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)return0;}-/* Configure the MDIO bus and connect the external PHY */-intemac_phy_config(structplatform_device*pdev,structemac_adapter*adpt)+staticintemac_mdio_bus_create(structplatform_device*pdev,+structemac_adapter*adpt){structdevice_node*np=pdev->dev.of_node;structmii_bus*mii_bus;intret;-/* Create the mii_bus object for talking to the MDIO bus */-adpt->mii_bus=mii_bus=devm_mdiobus_alloc(&pdev->dev);+mii_bus=devm_mdiobus_alloc(&pdev->dev);if(!mii_bus)return-ENOMEM;
@@ -115,50 +114,66 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)mii_bus->parent=&pdev->dev;mii_bus->priv=adpt;-if(has_acpi_companion(&pdev->dev)){-u32phy_addr;--ret=mdiobus_register(mii_bus);-if(ret){-dev_err(&pdev->dev,"could not register mdio bus\n");-returnret;-}-ret=device_property_read_u32(&pdev->dev,"phy-channel",-&phy_addr);-if(ret)-/* If we can't read a valid phy address, then assume-*thatthereisonlyonephyonthismdiobus.-*/-adpt->phydev=phy_find_first(mii_bus);-else-adpt->phydev=mdiobus_get_phy(mii_bus,phy_addr);--/* of_phy_find_device() claims a reference to the phydev,-*sowedothatheremanuallyaswell.Whenthedriver-*laterunloads,itcanunilaterallydropthereference-*withoutworryingaboutACPIvsDT.-*/-if(adpt->phydev)-get_device(&adpt->phydev->mdio.dev);-}else{-structdevice_node*phy_np;+ret=of_mdiobus_register(mii_bus,has_acpi_companion(&pdev->dev)?+NULL:np);+if(ret){+dev_err(&pdev->dev,"Could not register mdio bus\n");+returnret;+}-ret=of_mdiobus_register(mii_bus,np);-if(ret){-dev_err(&pdev->dev,"could not register mdio bus\n");-returnret;-}+adpt->mii_bus=mii_bus;+return0;+}+staticvoidemac_get_phydev(structplatform_device*pdev,+structemac_adapter*adpt)+{+structdevice_node*np=pdev->dev.of_node;+structmii_bus*bus=adpt->mii_bus;+structdevice_node*phy_np;+u32phy_addr;+intret;++if(!has_acpi_companion(&pdev->dev)){phy_np=of_parse_phandle(np,"phy-handle",0);adpt->phydev=of_phy_find_device(phy_np);of_node_put(phy_np);+return;}-if(!adpt->phydev){-dev_err(&pdev->dev,"could not find external phy\n");-mdiobus_unregister(mii_bus);-return-ENODEV;-}+ret=device_property_read_u32(&pdev->dev,"phy-channel",+&phy_addr);+if(ret)+/* If we can't read a valid phy address, then assume+*thatthereisonlyonephyonthismdiobus.+*/+adpt->phydev=phy_find_first(bus);+else+adpt->phydev=mdiobus_get_phy(bus,phy_addr);++/* of_phy_find_device() claims a reference to the phydev,+*sowedothatheremanuallyaswell.Whenthedriver+*laterunloads,itcanunilaterallydropthereference+*withoutworryingaboutACPIvsDT.+*/+if(adpt->phydev)+get_device(&adpt->phydev->mdio.dev);+}-return0;+/* Configure the MDIO bus and connect the external PHY */+intemac_phy_config(structplatform_device*pdev,structemac_adapter*adpt)+{+intret;++ret=emac_mdio_bus_create(pdev,adpt);+if(ret)+returnret;++emac_get_phydev(pdev,adpt);+if(adpt->phydev)+return0;++dev_err(&pdev->dev,"Could not find external phy\n");+mdiobus_unregister(adpt->mii_bus);+return-ENODEV;}
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-09-17 14:50:28
On Mon, Sep 17, 2018 at 04:53:29PM +0800, Wang Dongsheng wrote:
quoted hunk
This property copy from "ibm,emac.txt" to describe a shared MIDO bus.
Since emac include MDIO, so If the motherboard has more than one PHY
connected to an MDIO bus, this property will point to the MAC device
that has the MDIO bus.
Signed-off-by: Wang Dongsheng <redacted>
---
V2: s/Since QDF2400 emac/Since emac/
---
Documentation/devicetree/bindings/net/qcom-emac.txt | 4 ++++
1 file changed, 4 insertions(+)
On Mon, Sep 17, 2018 at 04:53:29PM +0800, Wang Dongsheng wrote:
quoted
This property copy from "ibm,emac.txt" to describe a shared MIDO bus.
Since emac include MDIO, so If the motherboard has more than one PHY
connected to an MDIO bus, this property will point to the MAC device
that has the MDIO bus.
Signed-off-by: Wang Dongsheng <redacted>
---
V2: s/Since QDF2400 emac/Since emac/
---
Documentation/devicetree/bindings/net/qcom-emac.txt | 4 ++++
1 file changed, 4 insertions(+)
Hi Dongsheng
I don't see why you need this property. The ethernet interface has a
phy-handle which points to a PHY. That is all you need to find the PHY.
phy-handle is description PHY address. This property is describing an
MDIO controller.
Each QCOM emac include an MDIO controller, normally each emac only
connect one
PHY device, but when all of the PHY devices mdio lines connect one MDIO
controller
that is included in EMAC, we need to share this MDIO controller for
others EMAC.
Normally:
(MDIO)
MAC0 ---------------------------------------PHY0
| |
| (DATA) |
---------------------------------------------
(MDIO)
MAC1 ---------------------------------------PHY1
| |
| (DATA) |
---------------------------------------------
Shared MDIO bus: "mdio-device" = &MAC0, MAC1 will get MAC0's MDIO bus
and also get the corresponding PHY device.
(DATA)
MAC0 ---------------------------------------PHY0
| |
| (MDIO) |
--------------------------------------------
|
MAC1 PHY0
| |
| (DATA) |
--------------------------------------------
Cheers,
Dongsheng
On Mon, Sep 17, 2018 at 04:53:29PM +0800, Wang Dongsheng wrote:
quoted
This property copy from "ibm,emac.txt" to describe a shared MIDO bus.
Since emac include MDIO, so If the motherboard has more than one PHY
connected to an MDIO bus, this property will point to the MAC device
that has the MDIO bus.
Signed-off-by: Wang Dongsheng <redacted>
---
V2: s/Since QDF2400 emac/Since emac/
---
Documentation/devicetree/bindings/net/qcom-emac.txt | 4 ++++
1 file changed, 4 insertions(+)
Hi Dongsheng
I don't see why you need this property. The ethernet interface has a
phy-handle which points to a PHY. That is all you need to find the PHY.
phy-handle is description PHY address. This property is describing an
MDIO controller.
Each QCOM emac include an MDIO controller, normally each emac only
connect one
PHY device, but when all of the PHY devices mdio lines connect one MDIO
controller
that is included in EMAC, we need to share this MDIO controller for
others EMAC.
If you want to describe the MDIO controller, then you embed a mdio
subnode into your Ethernet MAC node:
emac0: ethernet@feb20000 {
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
};
};
};
And then each Ethernet MAC controller refers to their appropriate PHY
device tree node using a phy-handle property to point to either their
own MDIO controller, or another MAC's MDIO controller.
The IBM Emac is a old (not to say bad) example and it does not use the
PHY library and the standard Device Tree node property, please don't use
it as a reference.
--
Florian
On Mon, Sep 17, 2018 at 04:53:29PM +0800, Wang Dongsheng wrote:
quoted
This property copy from "ibm,emac.txt" to describe a shared MIDO bus.
Since emac include MDIO, so If the motherboard has more than one PHY
connected to an MDIO bus, this property will point to the MAC device
that has the MDIO bus.
Signed-off-by: Wang Dongsheng <redacted>
---
V2: s/Since QDF2400 emac/Since emac/
---
Documentation/devicetree/bindings/net/qcom-emac.txt | 4 ++++
1 file changed, 4 insertions(+)
Hi Dongsheng
I don't see why you need this property. The ethernet interface has a
phy-handle which points to a PHY. That is all you need to find the PHY.
phy-handle is description PHY address. This property is describing an
MDIO controller.
Each QCOM emac include an MDIO controller, normally each emac only
connect one
PHY device, but when all of the PHY devices mdio lines connect one MDIO
controller
that is included in EMAC, we need to share this MDIO controller for
others EMAC.
If you want to describe the MDIO controller, then you embed a mdio
subnode into your Ethernet MAC node:
emac0: ethernet@feb20000 {
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
};
};
};
And then each Ethernet MAC controller refers to their appropriate PHY
device tree node using a phy-handle property to point to either their
own MDIO controller, or another MAC's MDIO controller.
Sorry, I do not understand how phy-handle point to MDIO controller,
because phy-handle is defined to point to a phy.
I suppose you mean:
mdio_node = of_get_parent(phy_node);
emac0: ethernet@feb20000 {
phy-handle = <&phy0>;
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
};
phy1: ethernet-phy@1 {
reg = <1>;
};
};
};
emac1: ethernet@fexxxxxx {
phy-handle = <&phy1>;
};
emac2: ethernet@fexxxxxx {
phy-handle = <&phy2>;
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy2: ethernet-phy@2 {
reg = <0>;
};
};
};
The IBM Emac is a old (not to say bad) example and it does not use the
PHY library and the standard Device Tree node property, please don't use
it as a reference.
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-09-18 12:35:45
quoted
If you want to describe the MDIO controller, then you embed a mdio
subnode into your Ethernet MAC node:
emac0: ethernet@feb20000 {
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
};
};
};
And then each Ethernet MAC controller refers to their appropriate PHY
device tree node using a phy-handle property to point to either their
own MDIO controller, or another MAC's MDIO controller.
Sorry, I do not understand how phy-handle point to MDIO controller,
because phy-handle is defined to point to a phy.
The MAC driver does not care what MDIO controller a PHY is on. All you
need to do to register the PHY is:
phy_node = of_parse_phandle(np, "phy-handle", 0);
phy_interface = of_get_phy_mode(np);
phydev = of_phy_connect(dev, phy_node,
&handle_link_change, 0,
phy_interface);
Andrew
If you want to describe the MDIO controller, then you embed a mdio
subnode into your Ethernet MAC node:
emac0: ethernet@feb20000 {
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
};
};
};
And then each Ethernet MAC controller refers to their appropriate PHY
device tree node using a phy-handle property to point to either their
own MDIO controller, or another MAC's MDIO controller.
Sorry, I do not understand how phy-handle point to MDIO controller,
because phy-handle is defined to point to a phy.
The MAC driver does not care what MDIO controller a PHY is on. All you
need to do to register the PHY is:
Yes, these are all things that must be done, and emac driver will
connect phy when mac up.
If we had a separate MDIO controller, the MAC would not care about MDIO
bus. But MDIO is integrated within the EMAC, and emac driver maintains
the mdio.
Each EMAC do their mdio register/unregister. But in the shared scenario,
the EMACs that use the shared bus do not need to create an MDIO and
cannot release the Shared bus.
In device tree environment as you and Florian said. Just use phy-handle
get the phy_node.
The EMAC would not care about the phy come from which MDIO bus because
the phy device gets from the device_node match(phy-handle). And if the
phy_dev cannot get through phy_node means, the mdio bus is not ready.
But ACPI environment my understand is this:
First method. EMAC driver gets the shared MDIO bus, and maintain it.
The second way, EMAC match the phy_dev from the name.
These patch series try to use the FIRST way. Now I prefer to use the
second way to do the shared function.
I will rework this patchset and maybe patches will be a delay for a few
days.
Cheers,
Dongsheng
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-09-19 12:25:21
On Wed, Sep 19, 2018 at 09:19:19AM +0000, Wang, Dongsheng wrote:
On 2018/9/18 20:35, Andrew Lunn wrote:
quoted
quoted
quoted
If you want to describe the MDIO controller, then you embed a mdio
subnode into your Ethernet MAC node:
emac0: ethernet@feb20000 {
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
};
};
};
And then each Ethernet MAC controller refers to their appropriate PHY
device tree node using a phy-handle property to point to either their
own MDIO controller, or another MAC's MDIO controller.
Sorry, I do not understand how phy-handle point to MDIO controller,
because phy-handle is defined to point to a phy.
The MAC driver does not care what MDIO controller a PHY is on. All you
need to do to register the PHY is:
Yes, these are all things that must be done, and emac driver will
connect phy when mac up.
If we had a separate MDIO controller, the MAC would not care about MDIO
bus. But MDIO is integrated within the EMAC, and emac driver maintains
the mdio.
Each EMAC do their mdio register/unregister. But in the shared scenario,
the EMACs that use the shared bus do not need to create an MDIO and
cannot release the Shared bus.
Hi Dongsheng
There is nothing new here. Many Ethernet drivers export an MDIO bus
which is then used by some other device, often an Ethernet
switch. Ordering should not be a problem, you just need to handle
EPROBE_DEFER, which will happen if the MDIO bus has not yet been
probed when you try to lookup the phy-handle. And once the phy has
been connected, the MDIO bus will be locked, preventing it from being
removed.
But ACPI environment my understand is this:
ACPI is completely separate and should not affect the DT binding.
I've not yet looked at the ACPI changes you added.
I will rework this patchset and maybe patches will be a delay for a few
days.
From: Timur Tabi <timur@kernel.org> Date: 2018-09-19 14:05:36
On 9/19/18 7:25 AM, Andrew Lunn wrote:
ACPI is completely separate and should not affect the DT binding.
I've not yet looked at the ACPI changes you added.
Just FYI, there is no device tree platform on which the upstream EMAC
driver works. All of the DT code in the driver is theoretical. It
worked once on a prototype platform, when I originally wrote the code,
but since then DT support is mostly a guess.
The focus of any patches for the EMAC should be ACPI, not DT. If
anything, ACPI support should come first. No one should be writing or
reviewing DT code before ACPI code.
The upstream EMAC driver is only known to work on the QDF2400, which is
an ACPI-only chip. I feel like I've been repeating this too often.
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-09-19 15:20:52
The focus of any patches for the EMAC should be ACPI, not DT. If anything,
ACPI support should come first. No one should be writing or reviewing DT
code before ACPI code.
I suspect that is not going to be easy. Last time i looked, the ACPI
standard had nothing about MDIO busses or PHYs. Marcin Wojtas did some
work in this area a while back for the mvpp2, but if i remember
correctly, he worked around this by simply not having a PHY when using
ACPI, and making use of a MAC interrupt which indicated when there was
link.
Whoever implements this first needs to be an ACPI expert and probably
needs to write it up and submit it as an amendment to the ACPI
standard.
Andrew
ACPI is completely separate and should not affect the DT binding.
I've not yet looked at the ACPI changes you added.
Just FYI, there is no device tree platform on which the upstream EMAC
driver works. All of the DT code in the driver is theoretical. It
worked once on a prototype platform, when I originally wrote the code,
but since then DT support is mostly a guess.
The focus of any patches for the EMAC should be ACPI, not DT. If
anything, ACPI support should come first. No one should be writing or
reviewing DT code before ACPI code.
The upstream EMAC driver is only known to work on the QDF2400, which is
an ACPI-only chip. I feel like I've been repeating this too often.
Ok, I just focus on ACPI, and keep DT code no changes.
Cheers,
Dongsheng
From: Timur Tabi <timur@kernel.org> Date: 2018-09-20 13:42:04
On 9/19/18 10:20 AM, Andrew Lunn wrote:
I suspect that is not going to be easy. Last time i looked, the ACPI
standard had nothing about MDIO busses or PHYs. Marcin Wojtas did some
work in this area a while back for the mvpp2, but if i remember
correctly, he worked around this by simply not having a PHY when using
ACPI, and making use of a MAC interrupt which indicated when there was
link.
Whoever implements this first needs to be an ACPI expert and probably
needs to write it up and submit it as an amendment to the ACPI
standard.
If that's what it takes, then so be it. But adding DT support for a
device that is only used on ACPI platforms is not a worthwhile endeavor.
After ACPI support is merged, Dongsheng can choose to add DT support to
maintain parity, if he wants. Maybe one day the MSM developers will use
the upstream driver on one of their SOCs.
From: Wang Dongsheng <hidden> Date: 2018-10-25 18:41:30
The emac include MDIO controller, and the motherboard has more than one
PHY connected to an MDIO bus. So share the shared mii_bus for others MAC
device that not has MDIO bus connected.
Based on ACPI, since "phy-handle" cannot directly point to a _DSD
sub-package, so we use "phy-handle" to point an internal MDIO device port.
The port describes the phy address.
Tested: QDF2400 (ACPI), buildin/insmod/rmmod
V3:
- Add "phy-handle" support.
- Remove all of DT changes.
V2:
- Separate patch.
Wang Dongsheng (2):
net: qcom/emac: split phy_config to mdio bus create and get phy device
net: qcom/emac: add phy-handle support for ACPI
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 183 ++++++++++++++----
1 file changed, 142 insertions(+), 41 deletions(-)
--
2.18.0
From: Wang Dongsheng <hidden> Date: 2018-10-25 18:41:39
This patch separate emac_mdio_bus_create and emac_get_phydev from
emac_phy_config, and do some codes clean.
Signed-off-by: Wang Dongsheng <redacted>
---
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 96 +++++++++++--------
1 file changed, 56 insertions(+), 40 deletions(-)
@@ -96,15 +96,15 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)return0;}-/* Configure the MDIO bus and connect the external PHY */-intemac_phy_config(structplatform_device*pdev,structemac_adapter*adpt)+staticintemac_mdio_bus_create(structplatform_device*pdev,+structemac_adapter*adpt){structdevice_node*np=pdev->dev.of_node;structmii_bus*mii_bus;intret;/* Create the mii_bus object for talking to the MDIO bus */-adpt->mii_bus=mii_bus=devm_mdiobus_alloc(&pdev->dev);+mii_bus=devm_mdiobus_alloc(&pdev->dev);if(!mii_bus)return-ENOMEM;
@@ -115,50 +115,66 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)mii_bus->parent=&pdev->dev;mii_bus->priv=adpt;-if(has_acpi_companion(&pdev->dev)){-u32phy_addr;--ret=mdiobus_register(mii_bus);-if(ret){-dev_err(&pdev->dev,"could not register mdio bus\n");-returnret;-}-ret=device_property_read_u32(&pdev->dev,"phy-channel",-&phy_addr);-if(ret)-/* If we can't read a valid phy address, then assume-*thatthereisonlyonephyonthismdiobus.-*/-adpt->phydev=phy_find_first(mii_bus);-else-adpt->phydev=mdiobus_get_phy(mii_bus,phy_addr);--/* of_phy_find_device() claims a reference to the phydev,-*sowedothatheremanuallyaswell.Whenthedriver-*laterunloads,itcanunilaterallydropthereference-*withoutworryingaboutACPIvsDT.-*/-if(adpt->phydev)-get_device(&adpt->phydev->mdio.dev);-}else{-structdevice_node*phy_np;--ret=of_mdiobus_register(mii_bus,np);-if(ret){-dev_err(&pdev->dev,"could not register mdio bus\n");-returnret;-}+ret=of_mdiobus_register(mii_bus,has_acpi_companion(&pdev->dev)?+NULL:np);+if(ret)+dev_err(&pdev->dev,"Could not register mdio bus\n");++adpt->mii_bus=ret?NULL:mii_bus;+returnret;+}++staticintemac_get_phydev(structplatform_device*pdev,+structemac_adapter*adpt)+{+structdevice_node*np=pdev->dev.of_node;+structmii_bus*bus=adpt->mii_bus;+structdevice_node*phy_np;+structphy_device*phydev;+u32phy_addr;+intret;++if(!has_acpi_companion(&pdev->dev)){phy_np=of_parse_phandle(np,"phy-handle",0);adpt->phydev=of_phy_find_device(phy_np);of_node_put(phy_np);+returnadpt->phydev?0:-ENODEV;}-if(!adpt->phydev){-dev_err(&pdev->dev,"could not find external phy\n");-mdiobus_unregister(mii_bus);+ret=device_property_read_u32(&pdev->dev,"phy-channel",+&phy_addr);+/* If we can't read a valid phy address, then assume+*thatthereisonlyonephyonthismdiobus.+*/+phydev=ret?phy_find_first(bus):mdiobus_get_phy(bus,phy_addr);+if(!phydev)return-ENODEV;-}+/* of_phy_find_device() claims a reference to the phydev,+*sowedothatheremanuallyaswell.Whenthedriver+*laterunloads,itcanunilaterallydropthereference+*withoutworryingaboutACPIvsDT.+*/+get_device(&phydev->mdio.dev);+adpt->phydev=phydev;return0;}++/* Configure the MDIO bus and connect the external PHY */+intemac_phy_config(structplatform_device*pdev,structemac_adapter*adpt)+{+intret;++ret=emac_mdio_bus_create(pdev,adpt);+if(ret)+returnret;++ret=emac_get_phydev(pdev,adpt);+if(ret){+dev_err(&pdev->dev,"Could not find external phy\n");+mdiobus_unregister(adpt->mii_bus);+}++returnret;+}
@@ -96,6 +96,96 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)return0;}+staticintacpi_device_match(structdevice*dev,void*fwnode)+{+returndev->fwnode==fwnode;+}++staticstructphy_device*+emac_acpi_get_phydev_from_phy_handle(structplatform_device*pdev)+{+structfwnode_reference_argsargs;+structfwnode_handle*fw_node;+structacpi_device*adev;+acpi_handlehandle;+structdevice*dev;+structphy_device*phydev;+structnet_device*netdev;+structemac_adapter*adpt;+intphy_addr;+intret;++/* Get PHY Port reference from phy-handle */+fw_node=acpi_fwnode_handle(ACPI_COMPANION(&pdev->dev));+ret=acpi_node_get_property_reference(fw_node,"phy-handle",0,+&args);+if(ACPI_FAILURE(ret)||!is_acpi_device_node(args.fwnode))+returnERR_PTR(-ENODEV);++/* Get PHY addr from the port node */+if(fwnode_property_read_u32(args.fwnode,"phy-channel",&phy_addr))+returnERR_PTR(-ENODEV);++/* Get the MDIO bus that included the port */+handle=ACPI_HANDLE_FWNODE(args.fwnode);+if(!handle||acpi_bus_get_device(handle,&adev))+returnERR_PTR(-ENODEV);++while(adev->parent){+if(!strcmp(acpi_device_hid(adev),"QCOM8070"))+break;+adev=adev->parent;+}+if(!adev->parent)+returnERR_PTR(-ENODEV);++dev=bus_find_device(&platform_bus_type,NULL,+&adev->fwnode,+acpi_device_match);+if(!dev)+returnERR_PTR(-ENODEV);++netdev=dev_get_drvdata(dev);+if(!netdev)+returnERR_PTR(-EPROBE_DEFER);++adpt=netdev_priv(netdev);+if(!adpt->mii_bus)+returnERR_PTR(-EPROBE_DEFER);++phydev=mdiobus_get_phy(adpt->mii_bus,phy_addr);+returnphydev?phydev:ERR_PTR(-ENODEV);+}++staticstructphy_device*+emac_acpi_get_phydev(structplatform_device*pdev,structemac_adapter*adpt)+{+structphy_device*phydev=NULL;+intphy_addr;+intret;++/* Compatible with "phy-channel" */+ret=device_property_read_u32(&pdev->dev,"phy-channel",+&phy_addr);+if(!ret)+phydev=mdiobus_get_phy(adpt->mii_bus,phy_addr);+if(phydev)+returnphydev;++/* Get PHY Port reference from phy-handle */+phydev=emac_acpi_get_phydev_from_phy_handle(pdev);+if(!IS_ERR(phydev))+returnphydev;+if(PTR_ERR(phydev)==-EPROBE_DEFER)+returnERR_PTR(-EPROBE_DEFER);++/* If we can't read a valid phy address from "phy-channel"/"phy-handle",+*thenassumethatthereisonlyonephyonlocalmdiobus.+*/+phydev=phy_find_first(adpt->mii_bus);+returnphydev?phydev:ERR_PTR(-ENODEV);+}+staticintemac_mdio_bus_create(structplatform_device*pdev,structemac_adapter*adpt){
@@ -128,13 +218,9 @@ static int emac_get_phydev(struct platform_device *pdev,structemac_adapter*adpt){structdevice_node*np=pdev->dev.of_node;-structmii_bus*bus=adpt->mii_bus;structdevice_node*phy_np;structphy_device*phydev;-u32phy_addr;-intret;-if(!has_acpi_companion(&pdev->dev)){phy_np=of_parse_phandle(np,"phy-handle",0);adpt->phydev=of_phy_find_device(phy_np);
@@ -142,14 +228,9 @@ static int emac_get_phydev(struct platform_device *pdev,returnadpt->phydev?0:-ENODEV;}-ret=device_property_read_u32(&pdev->dev,"phy-channel",-&phy_addr);-/* If we can't read a valid phy address, then assume-*thatthereisonlyonephyonthismdiobus.-*/-phydev=ret?phy_find_first(bus):mdiobus_get_phy(bus,phy_addr);-if(!phydev)-return-ENODEV;+phydev=emac_acpi_get_phydev(pdev,adpt);+if(IS_ERR(phydev))+returnPTR_ERR(phydev);/* of_phy_find_device() claims a reference to the phydev,*sowedothatheremanuallyaswell.Whenthedriver
@@ -171,10 +252,14 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)returnret;ret=emac_get_phydev(pdev,adpt);-if(ret){+if(!ret)+return0;++if(ret!=-EPROBE_DEFER)dev_err(&pdev->dev,"Could not find external phy\n");-mdiobus_unregister(adpt->mii_bus);-}+else+dev_warn(&pdev->dev,"Phy is not available yet, deferred probing\n");+mdiobus_unregister(adpt->mii_bus);returnret;}
On Thu, Oct 25, 2018 at 06:09:15PM +0800, Wang Dongsheng wrote:
quoted
Use "phy-handle" to porint an internal MDIO device port.
Hi Dongsheng
You are basically defining how all future ACPI based MAC drivers get
access to their PHY. This needs to become part of the ACPI standard,
etc.
This code should not be hidden away in the emac driver. It needs to be
placed somewhere public so other drivers can use it. And it needs good
documentation, including an example of what needs to go into the ACPI
tables, etc.
Hi Andrew
I saw AppliedMicro(apm) xgene has used "phy-handle" for ACPI method, so
I guess "phy-handle" has become part of the ACPI standard. But I cannot
make sure.
I tried to confirm the property is defined in the document(Like DT
binding). However, I did not find any documentation on the description
property definition on the UEFI/ACPICA website.
But when I was reading Documentation/acpi/DSD-properties-rules.txt, my
understanding is we should try to conform to DT bindings. So maybe ACPI
doesn't have such a document, just DT bindings.
Cheers,
Dongsheng
From: Timur Tabi <timur@kernel.org> Date: 2018-10-26 02:37:37
On 10/25/18 9:18 PM, Wang, Dongsheng wrote:
But when I was reading Documentation/acpi/DSD-properties-rules.txt, my
understanding is we should try to conform to DT bindings. So maybe ACPI
doesn't have such a document, just DT bindings.
But when I was reading Documentation/acpi/DSD-properties-rules.txt, my
understanding is we should try to conform to DT bindings. So maybe ACPI
doesn't have such a document, just DT bindings.
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-10-26 03:58:44
On Thu, Oct 25, 2018 at 06:09:15PM +0800, Wang Dongsheng wrote:
Use "phy-handle" to porint an internal MDIO device port.
Hi Dongsheng
You are basically defining how all future ACPI based MAC drivers get
access to their PHY. This needs to become part of the ACPI standard,
etc.
This code should not be hidden away in the emac driver. It needs to be
placed somewhere public so other drivers can use it. And it needs good
documentation, including an example of what needs to go into the ACPI
tables, etc.
Thanks
Andrew
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-10-26 13:13:01
On Fri, Oct 26, 2018 at 03:04:25AM +0000, Wang, Dongsheng wrote:
On 2018/10/26 10:37, Timur Tabi wrote:
quoted
On 10/25/18 9:18 PM, Wang, Dongsheng wrote:
quoted
But when I was reading Documentation/acpi/DSD-properties-rules.txt, my
understanding is we should try to conform to DT bindings. So maybe ACPI
doesn't have such a document, just DT bindings.
Yes, here's a database concept, and I asked some Intel guys, the answer
I got was there is no such database or document. :(
Hi Dongsheng
If there is no clear documentation for ACPI, it becomes even more
important that the xgene code is refactored into a central location,
and you make use of it. We really need to avoid every ACPI ethernet
driver doing its own thing.
Thanks
Andrew
On Fri, Oct 26, 2018 at 03:04:25AM +0000, Wang, Dongsheng wrote:
quoted
On 2018/10/26 10:37, Timur Tabi wrote:
quoted
On 10/25/18 9:18 PM, Wang, Dongsheng wrote:
quoted
But when I was reading Documentation/acpi/DSD-properties-rules.txt, my
understanding is we should try to conform to DT bindings. So maybe ACPI
doesn't have such a document, just DT bindings.
Yes, here's a database concept, and I asked some Intel guys, the answer
I got was there is no such database or document. :(
Hi Dongsheng
If there is no clear documentation for ACPI, it becomes even more
important that the xgene code is refactored into a central location,
and you make use of it. We really need to avoid every ACPI ethernet
driver doing its own thing.
However, without a document specifying MDIO and phy-handle, it is almost
difficult for us to do this. Because maybe the ACPI device or property
corresponding to each platform is different.
Just like APM looks different to us. APM's MDIO adev doesn't describe
the concept of port, and our platform does. Besides, I cannot get the
ACPI table of APM or other manufacturers.
The table of ACPI cannot be obtained from kernel source as easily as DT.
We can't know without a platform to do ACPI dump. Unless some of the
manufacturers have pushed the table to upstream.
So I think we might have a hard time doing this without a document. And
it's likely that this work involves code modifications by BIOS vendors.
Cheers,
Dongsheng
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-10-29 12:40:44
On Mon, Oct 29, 2018 at 02:39:36AM +0000, Wang, Dongsheng wrote:
On 2018/10/26 21:12, Andrew Lunn wrote:
quoted
On Fri, Oct 26, 2018 at 03:04:25AM +0000, Wang, Dongsheng wrote:
quoted
On 2018/10/26 10:37, Timur Tabi wrote:
quoted
On 10/25/18 9:18 PM, Wang, Dongsheng wrote:
quoted
But when I was reading Documentation/acpi/DSD-properties-rules.txt, my
understanding is we should try to conform to DT bindings. So maybe ACPI
doesn't have such a document, just DT bindings.
Yes, here's a database concept, and I asked some Intel guys, the answer
I got was there is no such database or document. :(
Hi Dongsheng
If there is no clear documentation for ACPI, it becomes even more
important that the xgene code is refactored into a central location,
and you make use of it. We really need to avoid every ACPI ethernet
driver doing its own thing.
However, without a document specifying MDIO and phy-handle, it is almost
difficult for us to do this. Because maybe the ACPI device or property
corresponding to each platform is different.
Just like APM looks different to us. APM's MDIO adev doesn't describe
the concept of port, and our platform does. Besides, I cannot get the
ACPI table of APM or other manufacturers.
The table of ACPI cannot be obtained from kernel source as easily as DT.
We can't know without a platform to do ACPI dump. Unless some of the
manufacturers have pushed the table to upstream.
So I think we might have a hard time doing this without a document. And
it's likely that this work involves code modifications by BIOS vendors.
Hi Dongsheng
There are two different options here.
1) Everybody does their own thing, ignoring what everybody else has
done, and invents their own wheel. There is no shared code, no shared
description, everybody has their own bugs, etc. ACPI as a standard is
pointless for Ethernet MDIOs and PHYs because it is not a standard,
everybody does something different.
2) Somebody takes the time to design a concept for Ethernet PHYs and
MDIO busses using ACPI. They implement the common code, try to modify
any existing users if possible, and submit the whole thing to become
part of ACPI 6.3.
I would really prefer we go the second route here. It is more initial
effort, but in the long run, everybody benefits.
Andrew
On Mon, Oct 29, 2018 at 02:39:36AM +0000, Wang, Dongsheng wrote:
quoted
On 2018/10/26 21:12, Andrew Lunn wrote:
quoted
On Fri, Oct 26, 2018 at 03:04:25AM +0000, Wang, Dongsheng wrote:
quoted
On 2018/10/26 10:37, Timur Tabi wrote:
quoted
On 10/25/18 9:18 PM, Wang, Dongsheng wrote:
quoted
But when I was reading Documentation/acpi/DSD-properties-rules.txt, my
understanding is we should try to conform to DT bindings. So maybe ACPI
doesn't have such a document, just DT bindings.
Yes, here's a database concept, and I asked some Intel guys, the answer
I got was there is no such database or document. :(
Hi Dongsheng
If there is no clear documentation for ACPI, it becomes even more
important that the xgene code is refactored into a central location,
and you make use of it. We really need to avoid every ACPI ethernet
driver doing its own thing.
However, without a document specifying MDIO and phy-handle, it is almost
difficult for us to do this. Because maybe the ACPI device or property
corresponding to each platform is different.
Just like APM looks different to us. APM's MDIO adev doesn't describe
the concept of port, and our platform does. Besides, I cannot get the
ACPI table of APM or other manufacturers.
The table of ACPI cannot be obtained from kernel source as easily as DT.
We can't know without a platform to do ACPI dump. Unless some of the
manufacturers have pushed the table to upstream.
So I think we might have a hard time doing this without a document. And
it's likely that this work involves code modifications by BIOS vendors.
Hi Dongsheng
There are two different options here.
1) Everybody does their own thing, ignoring what everybody else has
done, and invents their own wheel. There is no shared code, no shared
description, everybody has their own bugs, etc. ACPI as a standard is
pointless for Ethernet MDIOs and PHYs because it is not a standard,
everybody does something different.
2) Somebody takes the time to design a concept for Ethernet PHYs and
MDIO busses using ACPI. They implement the common code, try to modify
any existing users if possible, and submit the whole thing to become
part of ACPI 6.3.
I would really prefer we go the second route here. It is more initial
effort, but in the long run, everybody benefits.
Yes, I also would like the second one. I will reply in a few days.
Cheers,
Dongsheng
From: Wang Dongsheng <hidden> Date: 2018-11-08 07:21:29
Originally I just push "phy-handle" support for ACPI on the QCOM QDF2400
platform. After some discussion and following Andrew's advice, I send
out with a generic version of ACPI.
Current there is no clear documentation about MDIO/PHY for ACPI, so when
I reading some documents about ACPI [1], I think we just need to reuse the
DT binding in the ACPI.[2]. However, this series of patches are not
fully compatible with all contents specified in DT binding.
The most important thing about this iseries is link the phy device and
fwnode of acpi. Besides, we need to carry out bus scan at the mdio
register. Therefore, I am not compatible with more DT binding properties
in this series of patches. More support will be in the follow-up patches
support, or some people do the support.
Example:
Based on ACPI doc:
Documentation/acpi/dsd/data-node-references.txt
Documentation/acpi/dsd/graph.txt
With _DSD device properties we can finally do this:
Device (MDIO) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@0", PHY0 }, }
})
Name (PHY0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x0 }, }
})
}
Device (MACO) {
Name (_DSD, Package () {
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "phy-handle", \_SB.MDIO, "ethernet-phy@0" }, }
})
}
Tested: QDF2400 (ACPI), buildin/insmod/rmmod
[1]:
Documentation/acpi/dsd/data-node-references.txt
Documentation/acpi/dsd/graph.txt
[2]:
Documentation/devicetree/bindings/phy/phy-bindings.txt
https://lore.kernel.org/patchwork/patch/597296/
Wang Dongsheng (3):
acpi: Add acpi mdio support code
net: qcom/emac: split phy_config to mdio bus create and get phy device
net: qcom/emac: add phy-handle support for ACPI
drivers/acpi/Kconfig | 6 +
drivers/acpi/Makefile | 1 +
drivers/acpi/acpi_mdio.c | 167 ++++++++++++++++++
drivers/net/ethernet/qualcomm/emac/emac-mac.c | 19 +-
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 142 ++++++++++-----
drivers/net/phy/mdio_bus.c | 3 +
include/linux/acpi_mdio.h | 82 +++++++++
7 files changed, 369 insertions(+), 51 deletions(-)
create mode 100644 drivers/acpi/acpi_mdio.c
create mode 100644 include/linux/acpi_mdio.h
--
2.18.0
@@ -0,0 +1,167 @@+// SPDX-License-Identifier: GPL-2.0++// Lots of code in this file is copy from drivers/of/of_mdio.c+// Copyright (c) 2018 Huaxintong Semiconductor Technology Co., Ltd.++#include<linux/acpi.h>+#include<linux/acpi_mdio.h>+#include<linux/kernel.h>+#include<linux/device.h>+#include<linux/netdevice.h>+#include<linux/err.h>+#include<linux/phy.h>+#include<linux/phy_fixed.h>++/* Helper function for acpi_phy_find_device */+staticintphy_match(structdevice*dev,void*fwnode)+{+returndev->fwnode==fwnode;+}++/**+*acpi_phy_find_device-GiveaPHYfwnode,findthephy_device+*@fwnode:Pointertothephy'sacpidatanode+*+*Ifsuccessful,returnsapointertothephy_devicewiththeembedded+*structdevicerefcountincrementedbyone,orNULLonfailure.+*/+structphy_device*acpi_phy_find_device(structfwnode_handle*fwnode)+{+structdevice*d;+structmdio_device*mdiodev;++if(!fwnode)+returnNULL;++d=bus_find_device(&mdio_bus_type,NULL,fwnode,phy_match);+if(d){+mdiodev=to_mdio_device(d);+if(mdiodev->flags&MDIO_DEVICE_FLAG_PHY)+returnto_phy_device(d);+put_device(d);+}+returnNULL;+}+EXPORT_SYMBOL(acpi_phy_find_device);++staticintdo_acpi_mdiodev_match(structfwnode_handle*fwnode,+structmdio_device*mdiodev)+{+structdevice*dev=&mdiodev->dev;+structfwnode_handle*child_node;+intaddr;+intret;++fwnode_for_each_child_node(fwnode,child_node){+do{+addr=acpi_mdio_parse_addr(dev,child_node);+if(addr<0)+break;++if(mdiodev->addr!=addr)+break;++dev->fwnode=child_node;+return0;+}while(0);++/* Walk hierarchical extension data nodes */+ret=do_acpi_mdiodev_match(child_node,mdiodev);+if(!ret)+return0;+}++return-ENODEV;+}++/* Walk the list of subnodes of a mdio bus and look for a node that+*matchesthemdiodevice'saddresswithits'reg'property.If+*found,setthefwnodepointerforthemdiodevice.+*/+voidacpi_mdiobus_link_mdiodev(structmii_bus*bus,+structmdio_device*mdiodev)+{+structdevice*dev=&mdiodev->dev;++if(dev->fwnode||!bus->dev.fwnode)+return;++if(!has_acpi_companion(&bus->dev))+return;++do_acpi_mdiodev_match(bus->dev.fwnode,mdiodev);+}++/**+*acpi_phy_connect-Connecttothephy+*@dev:pointertonet_deviceclaimingthephy+*@fwnode:PointertoACPIdatanodeforthePHY+*@hndlr:Linkstatecallbackforthenetworkdevice+*@flags:flagstopasstothePHY+*@iface:PHYdatainterfacetype+*+*Ifsuccessful,returnsapointertothephy_devicewiththeembedded+*structdevicerefcountincrementedbyone,orNULLonfailure.The+*refcountmustbedroppedbycallingphy_disconnect()orphy_detach().+*/+structphy_device*acpi_phy_connect(structnet_device*dev,+structfwnode_handle*fwnode,+void(*hndlr)(structnet_device*),+u32flags,+phy_interface_tiface)+{+structphy_device*phy=acpi_phy_find_device(fwnode);+intret;++if(!phy)+returnNULL;++phy->dev_flags=flags;++ret=phy_connect_direct(dev,phy,hndlr,iface);++/* refcount is held by phy_connect_direct() on success */+put_device(&phy->mdio.dev);++returnret?NULL:phy;+}+EXPORT_SYMBOL(acpi_phy_connect);++staticintacpi_mdio_node_verify(structfwnode_handle*fwnode)+{+returnis_acpi_device_node(fwnode)?0:-ENODEV;+}++staticintfwnode_mdiobus_verify_node(structfwnode_handle*fwnode)+{+if(!is_acpi_node(fwnode))+return-ENODEV;+returnacpi_mdio_node_verify(fwnode);+}++/**+*acpi_mdiobus_register-Registermii_busandcreatePHYs+*@mdio:pointertomii_busstructure+*@fwnode:pointertofw_nodeofMDIObus.+*+*Thisfunctionregistersthemii_busstructureandscanthephy_devices+*foreachchildnodeof@fwnode.+*/+intacpi_mdiobus_register(structmii_bus*mdio,structfwnode_handle*fwnode)+{+intret;++if(!fwnode)+returnmdiobus_register(mdio);++ret=fwnode_mdiobus_verify_node(fwnode);+if(ret)+returnret;++/* Scan PHYs on MDIO bus */+mdio->phy_mask=0;+mdio->dev.fwnode=fwnode;++/* Register the MDIO bus */+returnmdiobus_register(mdio);+}+EXPORT_SYMBOL(acpi_mdiobus_register);
@@ -516,6 +517,8 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)*inthebusnode,andsettheof_nodepointerinthiscase.*/of_mdiobus_link_mdiodev(bus,&phydev->mdio);+/* Link the phy device with ACPI phy fwnode. */+acpi_mdiobus_link_mdiodev(bus,&phydev->mdio);err=phy_device_register(phydev);if(err){
@@ -0,0 +1,82 @@+/* SPDX-License-Identifier: GPL-2.0+ */+// Copyright (c) 2018 Huaxintong Semiconductor Technology Co., Ltd.++#ifndef __LINUX_ACPI_MDIO_H+#define __LINUX_ACPI_MDIO_H++#include<linux/acpi.h>+#include<linux/device.h>+#include<linux/phy.h>+#include<linux/property.h>++#if IS_ENABLED(CONFIG_ACPI_MDIO)+staticinlineintacpi_mdio_parse_addr(structdevice*dev,+conststructfwnode_handle*fwnode)+{+u32addr;++if(!is_acpi_data_node(fwnode))+return-ENODEV;++if(!fwnode_property_present(fwnode,"reg"))+return-ENODEV;++if(fwnode_property_read_u32(fwnode,"reg",&addr)){+dev_err(dev,"Invalid PHY address\n");+return-ENODEV;+}++/* A PHY must have a reg property in the range [0-31] */+if(addr>=PHY_MAX_ADDR){+dev_err(dev,"PHY address %i is too large\n",addr);+return-EINVAL;+}++returnaddr;+}++structphy_device*acpi_phy_find_device(structfwnode_handle*fwnode);+structphy_device*acpi_phy_connect(structnet_device*dev,+structfwnode_handle*fwnode,+void(*hndlr)(structnet_device*),+u32flags,phy_interface_tiface);+intacpi_mdiobus_register(structmii_bus*mdio,structfwnode_handle*fwnode);+voidacpi_mdiobus_link_mdiodev(structmii_bus*bus,+structmdio_device*mdiodev);+#else+staticinlineintacpi_mdio_parse_addr(structdevice*dev,+conststructfwnode_handle*fwnode)+{+return-EINVAL;+}++staticinlinestructphy_device*+acpi_phy_find_device(structfwnode_handle*fwnode)+{+returnNULL;+}++staticinlinestructphy_device*+acpi_phy_connect(structnet_device*dev,structfwnode_handle*fwnode,+void(*hndlr)(structnet_device*),u32flags,+phy_interface_tiface)+{+returnNULL;+}++staticinlineintacpi_mdiobus_register(structmii_bus*mdio,+structfwnode_handle*fwnode)+{+return-ENODEV;+}++staticinlinevoid+acpi_mdiobus_link_mdiodev(structmii_bus*bus,structmdio_device*mdiodev){}+#endif++staticinlinestructfwnode_handle*acpi_get_phy_node(structphy_device*phydev)+{+return!phydev?NULL:phydev->mdio.dev.fwnode;+}++#endif /* __LINUX_ACPI_MDIO_H */
From: Wang Dongsheng <hidden> Date: 2018-11-08 07:22:34
This patch separate emac_mdio_bus_create and emac_get_phydev from
emac_phy_config, and do some codes clean.
Signed-off-by: Wang Dongsheng <redacted>
---
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 96 +++++++++++--------
1 file changed, 56 insertions(+), 40 deletions(-)
@@ -96,15 +96,15 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)return0;}-/* Configure the MDIO bus and connect the external PHY */-intemac_phy_config(structplatform_device*pdev,structemac_adapter*adpt)+staticintemac_mdio_bus_create(structplatform_device*pdev,+structemac_adapter*adpt){structdevice_node*np=pdev->dev.of_node;structmii_bus*mii_bus;intret;/* Create the mii_bus object for talking to the MDIO bus */-adpt->mii_bus=mii_bus=devm_mdiobus_alloc(&pdev->dev);+mii_bus=devm_mdiobus_alloc(&pdev->dev);if(!mii_bus)return-ENOMEM;
@@ -115,50 +115,66 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)mii_bus->parent=&pdev->dev;mii_bus->priv=adpt;-if(has_acpi_companion(&pdev->dev)){-u32phy_addr;--ret=mdiobus_register(mii_bus);-if(ret){-dev_err(&pdev->dev,"could not register mdio bus\n");-returnret;-}-ret=device_property_read_u32(&pdev->dev,"phy-channel",-&phy_addr);-if(ret)-/* If we can't read a valid phy address, then assume-*thatthereisonlyonephyonthismdiobus.-*/-adpt->phydev=phy_find_first(mii_bus);-else-adpt->phydev=mdiobus_get_phy(mii_bus,phy_addr);--/* of_phy_find_device() claims a reference to the phydev,-*sowedothatheremanuallyaswell.Whenthedriver-*laterunloads,itcanunilaterallydropthereference-*withoutworryingaboutACPIvsDT.-*/-if(adpt->phydev)-get_device(&adpt->phydev->mdio.dev);-}else{-structdevice_node*phy_np;--ret=of_mdiobus_register(mii_bus,np);-if(ret){-dev_err(&pdev->dev,"could not register mdio bus\n");-returnret;-}+ret=of_mdiobus_register(mii_bus,has_acpi_companion(&pdev->dev)?+NULL:np);+if(ret)+dev_err(&pdev->dev,"Could not register mdio bus\n");++adpt->mii_bus=ret?NULL:mii_bus;+returnret;+}++staticintemac_get_phydev(structplatform_device*pdev,+structemac_adapter*adpt)+{+structdevice_node*np=pdev->dev.of_node;+structmii_bus*bus=adpt->mii_bus;+structdevice_node*phy_np;+structphy_device*phydev;+u32phy_addr;+intret;++if(!has_acpi_companion(&pdev->dev)){phy_np=of_parse_phandle(np,"phy-handle",0);adpt->phydev=of_phy_find_device(phy_np);of_node_put(phy_np);+returnadpt->phydev?0:-ENODEV;}-if(!adpt->phydev){-dev_err(&pdev->dev,"could not find external phy\n");-mdiobus_unregister(mii_bus);+ret=device_property_read_u32(&pdev->dev,"phy-channel",+&phy_addr);+/* If we can't read a valid phy address, then assume+*thatthereisonlyonephyonthismdiobus.+*/+phydev=ret?phy_find_first(bus):mdiobus_get_phy(bus,phy_addr);+if(!phydev)return-ENODEV;-}+/* of_phy_find_device() claims a reference to the phydev,+*sowedothatheremanuallyaswell.Whenthedriver+*laterunloads,itcanunilaterallydropthereference+*withoutworryingaboutACPIvsDT.+*/+get_device(&phydev->mdio.dev);+adpt->phydev=phydev;return0;}++/* Configure the MDIO bus and connect the external PHY */+intemac_phy_config(structplatform_device*pdev,structemac_adapter*adpt)+{+intret;++ret=emac_mdio_bus_create(pdev,adpt);+if(ret)+returnret;++ret=emac_get_phydev(pdev,adpt);+if(ret){+dev_err(&pdev->dev,"Could not find external phy\n");+mdiobus_unregister(adpt->mii_bus);+}++returnret;+}
From: Wang Dongsheng <hidden> Date: 2018-11-08 07:22:56
Use "phy-handle" to point to an internal MDIO device port.
Signed-off-by: Wang Dongsheng <redacted>
---
drivers/net/ethernet/qualcomm/emac/emac-mac.c | 19 ++---
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 78 ++++++++++++++-----
2 files changed, 70 insertions(+), 27 deletions(-)
@@ -17,6 +17,7 @@#include<linux/phy.h>#include<linux/iopoll.h>#include<linux/acpi.h>+#include<linux/acpi_mdio.h>#include"emac.h"/* EMAC base register offsets */
@@ -96,10 +97,60 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)return0;}+staticstructphy_device*+emac_acpi_get_phydev_from_phy_handle(structplatform_device*pdev)+{+structfwnode_reference_argsargs={0};+structfwnode_handle*fw_node;+structphy_device*phydev;+intret;++/* Get PHY Port reference from phy-handle */+fw_node=acpi_fwnode_handle(ACPI_COMPANION(&pdev->dev));+ret=acpi_node_get_property_reference(fw_node,"phy-handle",0,+&args);+if(ret)+returnERR_PTR(-ENODEV);++if(!is_acpi_data_node(args.fwnode))+returnERR_PTR(-ENODEV);++phydev=acpi_phy_find_device(args.fwnode);+returnphydev?phydev:ERR_PTR(-ENODEV);+}++staticstructphy_device*+emac_acpi_get_phydev(structplatform_device*pdev,structemac_adapter*adpt)+{+structphy_device*phydev=NULL;+intphy_addr;+intret;++/* Compatible with "phy-channel" */+ret=device_property_read_u32(&pdev->dev,"phy-channel",+&phy_addr);+if(!ret)+phydev=mdiobus_get_phy(adpt->mii_bus,phy_addr);+if(phydev)+returnphydev;++/* Get PHY Port reference from phy-handle */+phydev=emac_acpi_get_phydev_from_phy_handle(pdev);+if(!IS_ERR(phydev))+returnphydev;++/* If we can't read a valid phy address from "phy-channel"/"phy-handle",+*thenassumethatthereisonlyonephyonlocalmdiobus.+*/+phydev=phy_find_first(adpt->mii_bus);+returnphydev?phydev:ERR_PTR(-ENODEV);+}+staticintemac_mdio_bus_create(structplatform_device*pdev,structemac_adapter*adpt){structdevice_node*np=pdev->dev.of_node;+structfwnode_handle*fwnode=pdev->dev.fwnode;structmii_bus*mii_bus;intret;
@@ -115,8 +166,8 @@ static int emac_mdio_bus_create(struct platform_device *pdev,mii_bus->parent=&pdev->dev;mii_bus->priv=adpt;-ret=of_mdiobus_register(mii_bus,has_acpi_companion(&pdev->dev)?-NULL:np);+ret=is_of_node(fwnode)?of_mdiobus_register(mii_bus,np):+acpi_mdiobus_register(mii_bus,fwnode);if(ret)dev_err(&pdev->dev,"Could not register mdio bus\n");
@@ -128,13 +179,9 @@ static int emac_get_phydev(struct platform_device *pdev,structemac_adapter*adpt){structdevice_node*np=pdev->dev.of_node;-structmii_bus*bus=adpt->mii_bus;structdevice_node*phy_np;structphy_device*phydev;-u32phy_addr;-intret;-if(!has_acpi_companion(&pdev->dev)){phy_np=of_parse_phandle(np,"phy-handle",0);adpt->phydev=of_phy_find_device(phy_np);
@@ -142,14 +189,9 @@ static int emac_get_phydev(struct platform_device *pdev,returnadpt->phydev?0:-ENODEV;}-ret=device_property_read_u32(&pdev->dev,"phy-channel",-&phy_addr);-/* If we can't read a valid phy address, then assume-*thatthereisonlyonephyonthismdiobus.-*/-phydev=ret?phy_find_first(bus):mdiobus_get_phy(bus,phy_addr);-if(!phydev)-return-ENODEV;+phydev=emac_acpi_get_phydev(pdev,adpt);+if(IS_ERR(phydev))+returnPTR_ERR(phydev);/* of_phy_find_device() claims a reference to the phydev,*sowedothatheremanuallyaswell.Whenthedriver
@@ -171,10 +213,10 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)returnret;ret=emac_get_phydev(pdev,adpt);-if(ret){-dev_err(&pdev->dev,"Could not find external phy\n");-mdiobus_unregister(adpt->mii_bus);-}+if(!ret)+return0;+dev_err(&pdev->dev,"Could not find external phy\n");+mdiobus_unregister(adpt->mii_bus);returnret;}
@@ -0,0 +1,167 @@+// SPDX-License-Identifier: GPL-2.0++// Lots of code in this file is copy from drivers/of/of_mdio.c
Would it be possible to re-factor that code and share it instead?
I thought about it, we can actually do it with fwnode.
But I don't have a lot of concentrate to do this. I'm going to focus on
a few other things...:(
Maybe in the second half of 2019 I can re-factor them if there is no one
re-factor them.
Cheers,
Dongsheng
@@ -0,0 +1,167 @@+// SPDX-License-Identifier: GPL-2.0++// Lots of code in this file is copy from drivers/of/of_mdio.c
Would it be possible to re-factor that code and share it instead?
I thought about it, we can actually do it with fwnode.
But I don't have a lot of concentrate to do this. I'm going to focus on
a few other things...:(
Maybe in the second half of 2019 I can re-factor them if there is no one
re-factor them.
Well, I'd rather avoid code duplication upfront if possible.
Thanks,
Rafael
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-11-08 23:23:53
On Thu, Nov 08, 2018 at 03:21:29PM +0800, Wang Dongsheng wrote:
Originally I just push "phy-handle" support for ACPI on the QCOM QDF2400
platform. After some discussion and following Andrew's advice, I send
out with a generic version of ACPI.
Current there is no clear documentation about MDIO/PHY for ACPI, so when
I reading some documents about ACPI [1], I think we just need to reuse the
DT binding in the ACPI.[2]. However, this series of patches are not
fully compatible with all contents specified in DT binding.
The most important thing about this iseries is link the phy device and
fwnode of acpi. Besides, we need to carry out bus scan at the mdio
register. Therefore, I am not compatible with more DT binding properties
in this series of patches. More support will be in the follow-up patches
support, or some people do the support.
Example:
Based on ACPI doc:
Documentation/acpi/dsd/data-node-references.txt
Documentation/acpi/dsd/graph.txt
With _DSD device properties we can finally do this:
Device (MDIO) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@0", PHY0 }, }
})
Name (PHY0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x0 }, }
})
I don't know much about ACPI. I do know DT. MDIO busses can have
multiple PHYs on them. Is the following valid to list two PHYs?
Device (MDIO) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@0", PHY0 }, }
})
Name (PHY0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x0 }, }
})
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@10", PHY1 }, }
})
Name (PHY1, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x10 }, }
})
}
An MDIO bus can also have more than PHYs on them. There can be
Ethernet switches. Broadcom also have some with generic PHY devices on
them, and other odd things. That means whatever is on an MDIO bus is a
device in the Linux device model. How does that work? Do we need some
form Device (PHY) {}?
Device (MDIO) {
Device (PHY) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@0", PHY0 }, }
})
Name (PHY0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x0 }, }
})
}
Device (PHY) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@10", PHY1 }, }
})
Name (PHY1, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x10 }, }
})
Device (SWITCH) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "switch@11", SWITCH0 }, }
})
Name (SWITCH0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x11 }, }
})
}
}
I'm just trying to ensure whatever is defined is flexible enough that
we really can later support everything which DT does. We have PHYs on
MDIO busses, inside switches, which are on MDIO busses, which are
inside Ethernet interfaces, etc.
An MDIO bus is very similar to an i2c bus. How is that described in
ACPI? Anything we can learn from that?
Thanks
Andrew
From: Timur Tabi <timur@kernel.org> Date: 2018-11-09 00:37:25
On 11/8/18 5:23 PM, Andrew Lunn wrote:
I don't know much about ACPI. I do know DT. MDIO busses can have
multiple PHYs on them. Is the following valid to list two PHYs?
Device (MDIO) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@0", PHY0 }, }
})
Name (PHY0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x0 }, }
})
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@10", PHY1 }, }
})
Name (PHY1, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x10 }, }
})
}
You can't have the same DSD twice. It would need to look like this:
Name (PHY1, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0, 0x10 }, }
})
On Thu, Nov 08, 2018 at 03:21:29PM +0800, Wang Dongsheng wrote:
quoted
Originally I just push "phy-handle" support for ACPI on the QCOM QDF2400
platform. After some discussion and following Andrew's advice, I send
out with a generic version of ACPI.
Current there is no clear documentation about MDIO/PHY for ACPI, so when
I reading some documents about ACPI [1], I think we just need to reuse the
DT binding in the ACPI.[2]. However, this series of patches are not
fully compatible with all contents specified in DT binding.
The most important thing about this iseries is link the phy device and
fwnode of acpi. Besides, we need to carry out bus scan at the mdio
register. Therefore, I am not compatible with more DT binding properties
in this series of patches. More support will be in the follow-up patches
support, or some people do the support.
Example:
Based on ACPI doc:
Documentation/acpi/dsd/data-node-references.txt
Documentation/acpi/dsd/graph.txt
With _DSD device properties we can finally do this:
Device (MDIO) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@0", PHY0 }, }
})
Name (PHY0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x0 }, }
})
I don't know much about ACPI. I do know DT. MDIO busses can have
multiple PHYs on them. Is the following valid to list two PHYs?
Device (MDIO) {
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@0", PHY0 }, }
})
Name (PHY0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x0 }, }
})
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () { Package () { "ethernet-phy@10", PHY1 }, }
})
Name (PHY1, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () { Package () { "reg", 0x10 }, }
})
}
An MDIO bus can also have more than PHYs on them. There can be
Ethernet switches. Broadcom also have some with generic PHY devices on
them, and other odd things. That means whatever is on an MDIO bus is a
device in the Linux device model. How does that work? Do we need some
form Device (PHY) {}?
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b") describes a ACPI data node.
The data node can contain property or pointer.
Let's look at the table I'm using:
Device (MAC1)
{
// _DSD: Device-Specific Data
Name (_DSD, Package (0x02) {
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") /* Device
Properties for _DSD */,
Package (0x07) {
Package () { "phy-handle", Package () { \_SB.MAC1.MDIO,
"ethernet-phy@1" } },
Package () { "dev-refs", \_SB.MAC0 },
Package () { "refs0-dev", Package () { \_SB.MAC1.MDIO,
"refs@0" } },
Package () { "refs1-dev", Package () { \_SB.MAC1.MDIO,
"refs@1" } },
...
...
}
})
Device (MDIO)
{
Name (_DSD, Package () {
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
Package () {
Package () { "ethernet-phy@1", PHY1 },
Package () { "refs@0", REF0},
Package () { "refs@1", REF1},
}
})
//Contain a property
Name (PHY1, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () { "reg", 0x1 },
}
})
//Point to a device
Name (REF0, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () { "child-refs-dev", \_SB.MAC0 },
}
})
//Contain a property and a pointer that point to a device
Name (REF1, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () { "property", 0x5 },
Package () { "child-refs-dev", \_SB.MAC0 },
}
})
}
}
}
I'm just trying to ensure whatever is defined is flexible enough that
we really can later support everything which DT does. We have PHYs on
MDIO busses, inside switches, which are on MDIO busses, which are
inside Ethernet interfaces, etc.
I think it can be satisfied. See the table I'm using above.
An MDIO bus is very similar to an i2c bus. How is that described in
ACPI? Anything we can learn from that?
About the data node, I just read the Kernel Documentation/acpi/dsd/
And others learn from ACPI spec.
Cheers,
Dongsheng
I'm just trying to ensure whatever is defined is flexible enough that
we really can later support everything which DT does. We have PHYs on
MDIO busses, inside switches, which are on MDIO busses, which are
inside Ethernet interfaces, etc.
An MDIO bus is very similar to an i2c bus. How is that described in
ACPI? Anything we can learn from that?
All the documents I've seen are from UEFII/ACPICA and I have not seen any
independent description of MDIO in the ACPI documents. Maybe I missed a
document, too.
I think not all devices need to be described in ACPI. The ACPI defines what
should be included in a device, as well as some special definitions. Our
MDIO
doesn't need a special definition, because it's enough to use a generic ACPI
description. I think that's why MDIO doesn't have a separate description.
Cheers,
Dongsheng
From: Andrew Lunn <andrew@lunn.ch> Date: 2018-11-12 17:20:19
quoted
I'm just trying to ensure whatever is defined is flexible enough that
we really can later support everything which DT does. We have PHYs on
MDIO busses, inside switches, which are on MDIO busses, which are
inside Ethernet interfaces, etc.
I think it can be satisfied. See the table I'm using above.
Hi Dongsheng
Since i don't know anything better, i think i have to trust you have
this correct.
It would be good to document this, so that the next person who needs
to add ACPI support for a PHY has some documentation to look at.
Could you add something to Documentation/acpi/dsd?
Andrew
@@ -0,0 +1,167 @@+// SPDX-License-Identifier: GPL-2.0++// Lots of code in this file is copy from drivers/of/of_mdio.c+// Copyright (c) 2018 Huaxintong Semiconductor Technology Co., Ltd.
I agree with Rafael here. We should try to refactor and combine this
code. And where possible, we should try to add a uniform fwnode_ API
which underneath either uses OF or ACPI, depending on the type of the
node. We already have fwnode_get_mac_address(), fwmode_irq_get(),
fwnode_get_phy_mode(), so where possible, PHYs should be no different.
Andrew
Hello Rafael,
On 2018/11/13 1:19, Andrew Lunn wrote:
quoted
quoted
I'm just trying to ensure whatever is defined is flexible enough that
we really can later support everything which DT does. We have PHYs on
MDIO busses, inside switches, which are on MDIO busses, which are
inside Ethernet interfaces, etc.
I think it can be satisfied. See the table I'm using above.
Hi Dongsheng
Since i don't know anything better, i think i have to trust you have
this correct.
It would be good to document this, so that the next person who needs
to add ACPI support for a PHY has some documentation to look at.
Could you add something to Documentation/acpi/dsd?
How about Andrew suggestion? I agree with Andrew.
Or We need to add the documentation to Documentation/acpi?
I see that both GPIO and I2C are down here.
Cheers,
Dongsheng