Commit 975f6262 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dpaa2-ACPI'



Ioana Ciornei says:

====================
ACPI support for dpaa2 driver

This patch set provides ACPI support to DPAA2 network drivers.

It also introduces new fwnode based APIs to support phylink and phy
layers
    Following functions are defined:
      phylink_fwnode_phy_connect()
      fwnode_mdiobus_register_phy()
      fwnode_get_phy_id()
      fwnode_phy_find_device()
      device_phy_find_device()
      fwnode_get_phy_node()
      fwnode_mdio_find_device()
      acpi_get_local_address()

    First one helps in connecting phy to phylink instance.
    Next three helps in getting phy_id and registering phy to mdiobus
    Next two help in finding a phy on a mdiobus.
    Next one helps in getting phy_node from a fwnode.
    Last one is used to get local address from _ADR object.

    Corresponding OF functions are refactored.

Tested-on: LX2160ARDB

Changes in v9:
 - merged some minimal changes requested in the wording of the commit
   messages
 - fixed some build problems in patch 8/15 by moving the removal of
   of_find_mii_timestamper from patch 8/15 to 9/15.

Changes in v8:
 - fixed some checkpatch warnings/checks
 - included linux/fwnode_mdio.h in fwnode_mdio.c (fixed the build warnings)
 - added fwnode_find_mii_timestamper() and
   fwnode_mdiobus_phy_device_register() in order to get rid of the cycle
   dependency.
 - change to 'depends on (ACPI || OF) || COMPILE_TEST (for FWNODE_MDIO)
 - remove the fwnode_mdiobus_register from fwnode_mdio.c since it
   introduces a cycle of dependencies.

Changes in v7:
- correct fwnode_mdio_find_device() description
- check NULL in unregister_mii_timestamper()
- Call unregister_mii_timestamper() without NULL check
- Create fwnode_mdio.c and move fwnode_mdiobus_register_phy()
- include fwnode_mdio.h
- Include headers directly used in acpi_mdio.c
- Move fwnode_mdiobus_register() to fwnode_mdio.c
- Include fwnode_mdio.h
- Alphabetically sort header inclusions
- remove unnecassary checks

Changes in v6:
- Minor cleanup
- fix warning for function parameter of fwnode_mdio_find_device()
- Initialize mii_ts to NULL
- use GENMASK() and ACPI_COMPANION_SET()
- some cleanup
- remove unwanted header inclusion
- remove OF check for fixed-link
- use dev_fwnode()
- remove useless else
- replace of_device_is_available() to fwnode_device_is_available()

Changes in v5:
- More cleanup
- Replace fwnode_get_id() with acpi_get_local_address()
- add missing MODULE_LICENSE()
- replace fwnode_get_id() with OF and ACPI function calls
- replace fwnode_get_id() with OF and ACPI function calls

Changes in v4:
- More cleanup
- Improve code structure to handle all cases
- Remove redundant else from fwnode_mdiobus_register()
- Cleanup xgmac_mdio_probe()
- call phy_device_free() before returning

Changes in v3:
- Add more info on legacy DT properties "phy" and "phy-device"
- Redefine fwnode_phy_find_device() to follow of_phy_find_device()
- Use traditional comparison pattern
- Use GENMASK
- Modified to retrieve reg property value for ACPI as well
- Resolved compilation issue with CONFIG_ACPI = n
- Added more info into documentation
- Use acpi_mdiobus_register()
- Avoid unnecessary line removal
- Remove unused inclusion of acpi.h

Changes in v2:
- Updated with more description in document
- use reverse christmas tree ordering for local variables
- Refactor OF functions to use fwnode functions
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3e6dc7b6 3264f599
Loading
Loading
Loading
Loading
+133 −0
Original line number Diff line number Diff line
.. SPDX-License-Identifier: GPL-2.0

=========================
MDIO bus and PHYs in ACPI
=========================

The PHYs on an MDIO bus [1] are probed and registered using
fwnode_mdiobus_register_phy().

Later, for connecting these PHYs to their respective MACs, the PHYs registered
on the MDIO bus have to be referenced.

This document introduces two _DSD properties that are to be used
for connecting PHYs on the MDIO bus [3] to the MAC layer.

These properties are defined in accordance with the "Device
Properties UUID For _DSD" [2] document and the
daffd814-6eba-4d8c-8a91-bc9bbf4aa301 UUID must be used in the Device
Data Descriptors containing them.

phy-handle
----------
For each MAC node, a device property "phy-handle" is used to reference
the PHY that is registered on an MDIO bus. This is mandatory for
network interfaces that have PHYs connected to MAC via MDIO bus.

During the MDIO bus driver initialization, PHYs on this bus are probed
using the _ADR object as shown below and are registered on the MDIO bus.

::
      Scope(\_SB.MDI0)
      {
        Device(PHY1) {
          Name (_ADR, 0x1)
        } // end of PHY1

        Device(PHY2) {
          Name (_ADR, 0x2)
        } // end of PHY2
      }

Later, during the MAC driver initialization, the registered PHY devices
have to be retrieved from the MDIO bus. For this, the MAC driver needs
references to the previously registered PHYs which are provided
as device object references (e.g. \_SB.MDI0.PHY1).

phy-mode
--------
The "phy-mode" _DSD property is used to describe the connection to
the PHY. The valid values for "phy-mode" are defined in [4].

The following ASL example illustrates the usage of these properties.

DSDT entry for MDIO node
------------------------

The MDIO bus has an SoC component (MDIO controller) and a platform
component (PHYs on the MDIO bus).

a) Silicon Component
This node describes the MDIO controller, MDI0
---------------------------------------------
::
	Scope(_SB)
	{
	  Device(MDI0) {
	    Name(_HID, "NXP0006")
	    Name(_CCA, 1)
	    Name(_UID, 0)
	    Name(_CRS, ResourceTemplate() {
	      Memory32Fixed(ReadWrite, MDI0_BASE, MDI_LEN)
	      Interrupt(ResourceConsumer, Level, ActiveHigh, Shared)
	       {
		 MDI0_IT
	       }
	    }) // end of _CRS for MDI0
	  } // end of MDI0
	}

b) Platform Component
The PHY1 and PHY2 nodes represent the PHYs connected to MDIO bus MDI0
---------------------------------------------------------------------
::
	Scope(\_SB.MDI0)
	{
	  Device(PHY1) {
	    Name (_ADR, 0x1)
	  } // end of PHY1

	  Device(PHY2) {
	    Name (_ADR, 0x2)
	  } // end of PHY2
	}

DSDT entries representing MAC nodes
-----------------------------------

Below are the MAC nodes where PHY nodes are referenced.
phy-mode and phy-handle are used as explained earlier.
------------------------------------------------------
::
	Scope(\_SB.MCE0.PR17)
	{
	  Name (_DSD, Package () {
	     ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
		 Package () {
		     Package (2) {"phy-mode", "rgmii-id"},
		     Package (2) {"phy-handle", \_SB.MDI0.PHY1}
	      }
	   })
	}

	Scope(\_SB.MCE0.PR18)
	{
	  Name (_DSD, Package () {
	    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
		Package () {
		    Package (2) {"phy-mode", "rgmii-id"},
		    Package (2) {"phy-handle", \_SB.MDI0.PHY2}}
	    }
	  })
	}

References
==========

[1] Documentation/networking/phy.rst

[2] https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf

[3] Documentation/firmware-guide/acpi/DSD-properties-rules.rst

[4] Documentation/devicetree/bindings/net/ethernet-controller.yaml
+2 −0
Original line number Diff line number Diff line
@@ -6811,6 +6811,8 @@ F: Documentation/devicetree/bindings/net/mdio*
F:	Documentation/devicetree/bindings/net/qca,ar803x.yaml
F:	Documentation/networking/phy.rst
F:	drivers/net/mdio/
F:	drivers/net/mdio/acpi_mdio.c
F:	drivers/net/mdio/fwnode_mdio.c
F:	drivers/net/mdio/of_mdio.c
F:	drivers/net/pcs/
F:	drivers/net/phy/
+14 −0
Original line number Diff line number Diff line
@@ -277,6 +277,20 @@ acpi_evaluate_integer(acpi_handle handle,

EXPORT_SYMBOL(acpi_evaluate_integer);

int acpi_get_local_address(acpi_handle handle, u32 *addr)
{
	unsigned long long adr;
	acpi_status status;

	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
	if (ACPI_FAILURE(status))
		return -ENODATA;

	*addr = (u32)adr;
	return 0;
}
EXPORT_SYMBOL(acpi_get_local_address);

acpi_status
acpi_evaluate_reference(acpi_handle handle,
			acpi_string pathname,
+52 −36
Original line number Diff line number Diff line
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/* Copyright 2019 NXP */

#include <linux/acpi.h>
#include <linux/property.h>

#include "dpaa2-eth.h"
#include "dpaa2-mac.h"

@@ -34,39 +37,51 @@ static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode)
	return 0;
}

/* Caller must call of_node_put on the returned value */
static struct device_node *dpaa2_mac_get_node(u16 dpmac_id)
static struct fwnode_handle *dpaa2_mac_get_node(struct device *dev,
						u16 dpmac_id)
{
	struct device_node *dpmacs, *dpmac = NULL;
	u32 id;
	struct fwnode_handle *fwnode, *parent, *child  = NULL;
	struct device_node *dpmacs = NULL;
	int err;
	u32 id;

	fwnode = dev_fwnode(dev->parent);
	if (is_of_node(fwnode)) {
		dpmacs = of_find_node_by_name(NULL, "dpmacs");
		if (!dpmacs)
			return NULL;
		parent = of_fwnode_handle(dpmacs);
	} else if (is_acpi_node(fwnode)) {
		parent = fwnode;
	}

	while ((dpmac = of_get_next_child(dpmacs, dpmac)) != NULL) {
		err = of_property_read_u32(dpmac, "reg", &id);
	fwnode_for_each_child_node(parent, child) {
		err = -EINVAL;
		if (is_acpi_device_node(child))
			err = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &id);
		else if (is_of_node(child))
			err = of_property_read_u32(to_of_node(child), "reg", &id);
		if (err)
			continue;
		if (id == dpmac_id)
			break;
	}

		if (id == dpmac_id) {
			of_node_put(dpmacs);

	return dpmac;
			return child;
		}
	}
	of_node_put(dpmacs);
	return NULL;
}

static int dpaa2_mac_get_if_mode(struct device_node *node,
static int dpaa2_mac_get_if_mode(struct fwnode_handle *dpmac_node,
				 struct dpmac_attr attr)
{
	phy_interface_t if_mode;
	int err;

	err = of_get_phy_mode(node, &if_mode);
	if (!err)
		return if_mode;
	err = fwnode_get_phy_mode(dpmac_node);
	if (err > 0)
		return err;

	err = phy_mode(attr.eth_if, &if_mode);
	if (!err)
@@ -235,26 +250,27 @@ static const struct phylink_mac_ops dpaa2_mac_phylink_ops = {
};

static int dpaa2_pcs_create(struct dpaa2_mac *mac,
			    struct device_node *dpmac_node, int id)
			    struct fwnode_handle *dpmac_node,
			    int id)
{
	struct mdio_device *mdiodev;
	struct device_node *node;
	struct fwnode_handle *node;

	node = of_parse_phandle(dpmac_node, "pcs-handle", 0);
	if (!node) {
	node = fwnode_find_reference(dpmac_node, "pcs-handle", 0);
	if (IS_ERR(node)) {
		/* do not error out on old DTS files */
		netdev_warn(mac->net_dev, "pcs-handle node not found\n");
		return 0;
	}

	if (!of_device_is_available(node)) {
	if (!fwnode_device_is_available(node)) {
		netdev_err(mac->net_dev, "pcs-handle node not available\n");
		of_node_put(node);
		fwnode_handle_put(node);
		return -ENODEV;
	}

	mdiodev = of_mdio_find_device(node);
	of_node_put(node);
	mdiodev = fwnode_mdio_find_device(node);
	fwnode_handle_put(node);
	if (!mdiodev)
		return -EPROBE_DEFER;

@@ -283,13 +299,13 @@ static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
int dpaa2_mac_connect(struct dpaa2_mac *mac)
{
	struct net_device *net_dev = mac->net_dev;
	struct device_node *dpmac_node;
	struct fwnode_handle *dpmac_node;
	struct phylink *phylink;
	int err;

	mac->if_link_type = mac->attr.link_type;

	dpmac_node = mac->of_node;
	dpmac_node = mac->fw_node;
	if (!dpmac_node) {
		netdev_err(net_dev, "No dpmac@%d node found.\n", mac->attr.id);
		return -ENODEV;
@@ -304,7 +320,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
	 * error out if the interface mode requests them and there is no PHY
	 * to act upon them
	 */
	if (of_phy_is_fixed_link(dpmac_node) &&
	if (of_phy_is_fixed_link(to_of_node(dpmac_node)) &&
	    (mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID ||
	     mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
	     mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) {
@@ -324,7 +340,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
	mac->phylink_config.type = PHYLINK_NETDEV;

	phylink = phylink_create(&mac->phylink_config,
				 of_fwnode_handle(dpmac_node), mac->if_mode,
				 dpmac_node, mac->if_mode,
				 &dpaa2_mac_phylink_ops);
	if (IS_ERR(phylink)) {
		err = PTR_ERR(phylink);
@@ -335,9 +351,9 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
	if (mac->pcs)
		phylink_set_pcs(mac->phylink, &mac->pcs->pcs);

	err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0);
	err = phylink_fwnode_phy_connect(mac->phylink, dpmac_node, 0);
	if (err) {
		netdev_err(net_dev, "phylink_of_phy_connect() = %d\n", err);
		netdev_err(net_dev, "phylink_fwnode_phy_connect() = %d\n", err);
		goto err_phylink_destroy;
	}

@@ -384,8 +400,8 @@ int dpaa2_mac_open(struct dpaa2_mac *mac)
	/* Find the device node representing the MAC device and link the device
	 * behind the associated netdev to it.
	 */
	mac->of_node = dpaa2_mac_get_node(mac->attr.id);
	net_dev->dev.of_node = mac->of_node;
	mac->fw_node = dpaa2_mac_get_node(&mac->mc_dev->dev, mac->attr.id);
	net_dev->dev.of_node = to_of_node(mac->fw_node);

	return 0;

@@ -399,8 +415,8 @@ void dpaa2_mac_close(struct dpaa2_mac *mac)
	struct fsl_mc_device *dpmac_dev = mac->mc_dev;

	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
	if (mac->of_node)
		of_node_put(mac->of_node);
	if (mac->fw_node)
		fwnode_handle_put(mac->fw_node);
}

static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = {
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ struct dpaa2_mac {
	phy_interface_t if_mode;
	enum dpmac_link_type if_link_type;
	struct lynx_pcs *pcs;
	struct device_node *of_node;
	struct fwnode_handle *fw_node;
};

bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev,
Loading