Add basic ACPI support to the Qualcomm Technologies EMAC driver
Subsystems (3)
v2 cover Add basic ACPI support to the Qualcomm Technologies EMAC driver
This patch series adds support to the EMAC driver for extracting addresses, interrupts, and some _DSDs (properties) from ACPI. The first two patches clean up the code, and the third patch adds ACPI-specific functionality.
The first patch fixes a bug with handling the platform_device for the internal PHY. This phy is treated as a separate device in both DT and ACPI, but since the platform is not released automatically when the driver unloads, managed functions like devm_ioremap_resource cannot be used.
The second patch replaces of_get_mac_address with its platform-independent equivalent device_get_mac_address.
The third patch parses the ACPI tables to obtain the platform_device for the primary EMAC node ("QCOM8070") and the internal phy node ("QCOM8071").
Timur Tabi (3):
[v2] net: qcom/emac: do not use devm on internal phy pdev [v2] net: qcom/emac: use device_get_mac_address [v2] net: qcom/emac: initial ACPI support
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 37 ++++++-- drivers/net/ethernet/qualcomm/emac/emac-sgmii.c | 110 ++++++++++++++++++------ drivers/net/ethernet/qualcomm/emac/emac.c | 26 ++++-- 3 files changed, 134 insertions(+), 39 deletions(-)
Signature · 3 lines
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH v2 1/3 net: qcom/emac: do not use devm on internal phy pdev
The platform_device returned by of_find_device_by_node() is not automatically released when the driver unprobes. Therefore, managed calls like devm_ioremap_resource() should not be used. Instead, we manually allocate the resources and then free them on driver release.
--- drivers/net/ethernet/qualcomm/emac/emac-sgmii.c | 42 +++++++++++++++++++------ drivers/net/ethernet/qualcomm/emac/emac.c | 4 +++ 2 files changed, 37 insertions(+), 9 deletions(-)
drivers/net/ethernet/qualcomm/emac/emac-sgmii.c +33 -9
@@ -681,6 +681,7 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)struct resource *res;const struct of_device_id *match;struct device_node *np; +int ret; np =of_parse_phandle (pdev->dev.of_node,"internal-phy" ,0 );if (!np) {
@@ -697,25 +698,48 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt) match =of_match_device (emac_sgmii_dt_match, &sgmii_pdev->dev);if (!match) {dev_err (&pdev->dev,"unrecognized internal phy node\n" ); -return -ENODEV ; + ret = -ENODEV ; + goto error_put_device; } phy->initialize = (emac_sgmii_initialize )match->data;/* Base address is the first address */ res =platform_get_resource (sgmii_pdev,IORESOURCE_MEM ,0 ); - phy->base =devm_ioremap_resource (&sgmii_pdev->dev, res); -if (IS_ERR (phy->base)) -return PTR_ERR (phy->base); + phy->base =ioremap (res->start,resource_size (res)); +if (IS_ERR (phy->base)) { + ret =PTR_ERR (phy->base); + goto error_put_device; + }/* v2 SGMII has a per-lane digital digital, so parse it if it exists */ res =platform_get_resource (sgmii_pdev,IORESOURCE_MEM ,1 );if (res) { - phy->digital =devm_ioremap_resource (&sgmii_pdev->dev, res); -if (IS_ERR (phy->base)) -return PTR_ERR (phy->base); - + phy->digital =ioremap (res->start,resource_size (res)); +if (IS_ERR (phy->digital)) { + ret =PTR_ERR (phy->digital); + goto error_unmap_base; + } } -return phy->initialize (adpt); + ret = phy->initialize (adpt); +if (ret) + goto error; + +/* We've remapped the addresses, so we don't need the device any +* more. of_find_device_by_node() says we should release it. +*/ +put_device (&sgmii_pdev->dev); + +return 0 ; + +error: +if (phy->digital) +iounmap (phy->digital); +error_unmap_base: +iounmap (phy->base); +error_put_device: +put_device (&sgmii_pdev->dev); + +return ret; }
drivers/net/ethernet/qualcomm/emac/emac.c +4 -0
@@ -723,6 +723,10 @@ static int emac_remove(struct platform_device *pdev)mdiobus_unregister (adpt->mii_bus);free_netdev (netdev); +if (adpt->phy.digital) +iounmap (adpt->phy.digital); +iounmap (adpt->phy.base); +return 0 ; }
Signature · 3 lines
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH v2 2/3 net: qcom/emac: use device_get_mac_address
In reply to Timur TabiReplace the DT-specific of_get_mac_address() function with device_get_mac_address, which works on both DT and ACPI platforms. This change makes it easier to add ACPI support.
--- drivers/net/ethernet/qualcomm/emac/emac.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
drivers/net/ethernet/qualcomm/emac/emac.c +4 -6
@@ -531,18 +531,16 @@ static void emac_clks_teardown(struct emac_adapter *adpt)static int emac_probe_resources (struct platform_device *pdev,struct emac_adapter *adpt) { -struct device_node *node = pdev->dev.of_node;struct net_device *netdev = adpt->netdev;struct resource *res; -const void *maddr; +char maddr[ETH_ALEN ];int ret =0 ;/* get mac address */ - maddr =of_get_mac_address (node); -if (!maddr) -eth_hw_addr_random (netdev); -else +if (device_get_mac_address (&pdev->dev, maddr,ETH_ALEN ))ether_addr_copy (netdev->dev_addr, maddr); +else +eth_hw_addr_random (netdev);/* Core 0 interrupt */ ret =platform_get_irq (pdev,0 );
Signature · 3 lines
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH v2 3/3 net: qcom/emac: initial ACPI support
In reply to Timur TabiAdd support for reading addresses, interrupts, and _DSD properties from ACPI tables, just like with device tree. The HID for the EMAC device itself is QCOM8070. The internal PHY is represented by a child node with a HID of QCOM8071.
The EMAC also has some complex clock initialization requirements that are not represented by this patch. This will be addressed in a future patch.
--- drivers/net/ethernet/qualcomm/emac/emac-phy.c | 37 ++++++++++--- drivers/net/ethernet/qualcomm/emac/emac-sgmii.c | 72 ++++++++++++++++++------- drivers/net/ethernet/qualcomm/emac/emac.c | 12 +++++ 3 files changed, 95 insertions(+), 26 deletions(-)
drivers/net/ethernet/qualcomm/emac/emac-phy.c +30 -7
@@ -19,6 +19,7 @@#include <linux/of_mdio.h> #include <linux/phy.h> #include <linux/iopoll.h> +#include <linux/acpi.h> #include "emac.h" #include "emac-mac.h" #include "emac-phy.h"
@@ -167,7 +168,6 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)int emac_phy_config (struct platform_device *pdev,struct emac_adapter *adpt) {struct device_node *np = pdev->dev.of_node; -struct device_node *phy_np;struct mii_bus *mii_bus;int ret;
@@ -183,14 +183,37 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt) mii_bus->parent = &pdev->dev; mii_bus->priv = adpt; - ret =of_mdiobus_register (mii_bus, np); -if (ret) { -dev_err (&pdev->dev,"could not register mdio bus\n" ); -return ret; +if (has_acpi_companion (&pdev->dev)) { +u32 phy_addr; + + ret =mdiobus_register (mii_bus); +if (ret) { +dev_err (&pdev->dev,"could not register mdio bus\n" ); +return ret; + } + ret =device_property_read_u32 (&pdev->dev,"phy-channel" , + &phy_addr); +if (ret) +/* If we can't read a valid phy address, then assume +* that there is only one phy on this mdio bus. +*/ + adpt->phydev =phy_find_first (mii_bus); +else + adpt->phydev =mdiobus_get_phy (mii_bus, phy_addr); + + }else { +struct device_node *phy_np; + + ret =of_mdiobus_register (mii_bus, np); +if (ret) { +dev_err (&pdev->dev,"could not register mdio bus\n" ); +return ret; + } + + phy_np =of_parse_phandle (np,"phy-handle" ,0 ); + adpt->phydev =of_phy_find_device (phy_np); } - phy_np =of_parse_phandle (np,"phy-handle" ,0 ); - adpt->phydev =of_phy_find_device (phy_np);if (!adpt->phydev) {dev_err (&pdev->dev,"could not find external phy\n" );mdiobus_unregister (mii_bus);
drivers/net/ethernet/qualcomm/emac/emac-sgmii.c +53 -19
95 lines not on this page · raw message
drivers/net/ethernet/qualcomm/emac/emac.c +12 -0
@@ -22,6 +22,7 @@#include <linux/of_device.h> #include <linux/phy.h> #include <linux/platform_device.h> +#include <linux/acpi.h> #include "emac.h" #include "emac-mac.h" #include "emac-phy.h"
@@ -575,6 +576,16 @@ static const struct of_device_id emac_dt_match[] = { {} }; +#if IS_ENABLED (CONFIG_ACPI ) +static const struct acpi_device_id emac_acpi_match[] = { + { + .id ="QCOM8070" , + }, + {} +}; +MODULE_DEVICE_TABLE (acpi, emac_acpi_match); +#endif +static int emac_probe (struct platform_device *pdev) {struct net_device *netdev;
@@ -734,6 +745,7 @@ static struct platform_driver emac_platform_driver = { .driver = { .name = "qcom-emac", .of_match_table = emac_dt_match, + .acpi_match_table = ACPI_PTR(emac_acpi_match), }, };
Signature · 3 lines
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
David Miller
maintainerFrom: Timur Tabi <[email protected]>
Date: Wed, 28 Sep 2016 11:58:41 -0500
Quoted 10 lines
This patch series adds support to the EMAC driver for extracting addresses, interrupts, and some
_DSDs(properties) from ACPI. The first two patches clean up the code, and the third patch adds ACPI-specific functionality.The first patch fixes a bug with handling the
platform_devicefor the internal PHY. This phy is treated as a separate device in both DT and ACPI, but since the platform is not released automatically when the driver unloads, managed functions likedevm_ioremap_resourcecannot be used.
Quoted 5 lines
The second patch replaces
of_get_mac_addresswith its platform-independent equivalentdevice_get_mac_address.The third patch parses the ACPI tables to obtain the
platform_devicefor the primary EMAC node ("QCOM8070") and the internal phy node ("QCOM8071").
Series applied, thanks.