aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimur Tabi <timur@codeaurora.org>2016-09-28 12:58:44 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-29 01:50:13 -0400
commit5f3d38078c84f7bc12739a3b79fc59797cf0262d (patch)
tree45498ce13c16891134fde2b82b3d0eb93315e1f5
parent0de709acbc0d0001dc4b0953aebcfb0f030b9b0e (diff)
net: qcom/emac: initial ACPI support
Add 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. Signed-off-by: Timur Tabi <timur@codeaurora.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-phy.c37
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii.c72
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac.c12
3 files changed, 95 insertions, 26 deletions
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-phy.c b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
index c412ba9a27e7..da4e90db4d98 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-phy.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
@@ -19,6 +19,7 @@
19#include <linux/of_mdio.h> 19#include <linux/of_mdio.h>
20#include <linux/phy.h> 20#include <linux/phy.h>
21#include <linux/iopoll.h> 21#include <linux/iopoll.h>
22#include <linux/acpi.h>
22#include "emac.h" 23#include "emac.h"
23#include "emac-mac.h" 24#include "emac-mac.h"
24#include "emac-phy.h" 25#include "emac-phy.h"
@@ -167,7 +168,6 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
167int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt) 168int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
168{ 169{
169 struct device_node *np = pdev->dev.of_node; 170 struct device_node *np = pdev->dev.of_node;
170 struct device_node *phy_np;
171 struct mii_bus *mii_bus; 171 struct mii_bus *mii_bus;
172 int ret; 172 int ret;
173 173
@@ -183,14 +183,37 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
183 mii_bus->parent = &pdev->dev; 183 mii_bus->parent = &pdev->dev;
184 mii_bus->priv = adpt; 184 mii_bus->priv = adpt;
185 185
186 ret = of_mdiobus_register(mii_bus, np); 186 if (has_acpi_companion(&pdev->dev)) {
187 if (ret) { 187 u32 phy_addr;
188 dev_err(&pdev->dev, "could not register mdio bus\n"); 188
189 return ret; 189 ret = mdiobus_register(mii_bus);
190 if (ret) {
191 dev_err(&pdev->dev, "could not register mdio bus\n");
192 return ret;
193 }
194 ret = device_property_read_u32(&pdev->dev, "phy-channel",
195 &phy_addr);
196 if (ret)
197 /* If we can't read a valid phy address, then assume
198 * that there is only one phy on this mdio bus.
199 */
200 adpt->phydev = phy_find_first(mii_bus);
201 else
202 adpt->phydev = mdiobus_get_phy(mii_bus, phy_addr);
203
204 } else {
205 struct device_node *phy_np;
206
207 ret = of_mdiobus_register(mii_bus, np);
208 if (ret) {
209 dev_err(&pdev->dev, "could not register mdio bus\n");
210 return ret;
211 }
212
213 phy_np = of_parse_phandle(np, "phy-handle", 0);
214 adpt->phydev = of_phy_find_device(phy_np);
190 } 215 }
191 216
192 phy_np = of_parse_phandle(np, "phy-handle", 0);
193 adpt->phydev = of_phy_find_device(phy_np);
194 if (!adpt->phydev) { 217 if (!adpt->phydev) {
195 dev_err(&pdev->dev, "could not find external phy\n"); 218 dev_err(&pdev->dev, "could not find external phy\n");
196 mdiobus_unregister(mii_bus); 219 mdiobus_unregister(mii_bus);
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
index ad0e4209d948..3d2c05a40d2c 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
@@ -14,6 +14,7 @@
14 */ 14 */
15 15
16#include <linux/iopoll.h> 16#include <linux/iopoll.h>
17#include <linux/acpi.h>
17#include <linux/of_device.h> 18#include <linux/of_device.h>
18#include "emac.h" 19#include "emac.h"
19#include "emac-mac.h" 20#include "emac-mac.h"
@@ -662,6 +663,24 @@ void emac_sgmii_reset(struct emac_adapter *adpt)
662 clk_set_rate(adpt->clk[EMAC_CLK_HIGH_SPEED], 125000000); 663 clk_set_rate(adpt->clk[EMAC_CLK_HIGH_SPEED], 125000000);
663} 664}
664 665
666static int emac_sgmii_acpi_match(struct device *dev, void *data)
667{
668 static const struct acpi_device_id match_table[] = {
669 {
670 .id = "QCOM8071",
671 .driver_data = (kernel_ulong_t)emac_sgmii_init_v2,
672 },
673 {}
674 };
675 const struct acpi_device_id *id = acpi_match_device(match_table, dev);
676 emac_sgmii_initialize *initialize = data;
677
678 if (id)
679 *initialize = (emac_sgmii_initialize)id->driver_data;
680
681 return !!id;
682}
683
665static const struct of_device_id emac_sgmii_dt_match[] = { 684static const struct of_device_id emac_sgmii_dt_match[] = {
666 { 685 {
667 .compatible = "qcom,fsm9900-emac-sgmii", 686 .compatible = "qcom,fsm9900-emac-sgmii",
@@ -679,30 +698,45 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
679 struct platform_device *sgmii_pdev = NULL; 698 struct platform_device *sgmii_pdev = NULL;
680 struct emac_phy *phy = &adpt->phy; 699 struct emac_phy *phy = &adpt->phy;
681 struct resource *res; 700 struct resource *res;
682 const struct of_device_id *match;
683 struct device_node *np;
684 int ret; 701 int ret;
685 702
686 np = of_parse_phandle(pdev->dev.of_node, "internal-phy", 0); 703 if (has_acpi_companion(&pdev->dev)) {
687 if (!np) { 704 struct device *dev;
688 dev_err(&pdev->dev, "missing internal-phy property\n");
689 return -ENODEV;
690 }
691 705
692 sgmii_pdev = of_find_device_by_node(np); 706 dev = device_find_child(&pdev->dev, &phy->initialize,
693 if (!sgmii_pdev) { 707 emac_sgmii_acpi_match);
694 dev_err(&pdev->dev, "invalid internal-phy property\n");
695 return -ENODEV;
696 }
697 708
698 match = of_match_device(emac_sgmii_dt_match, &sgmii_pdev->dev); 709 if (!dev) {
699 if (!match) { 710 dev_err(&pdev->dev, "cannot find internal phy node\n");
700 dev_err(&pdev->dev, "unrecognized internal phy node\n"); 711 return -ENODEV;
701 ret = -ENODEV; 712 }
702 goto error_put_device;
703 }
704 713
705 phy->initialize = (emac_sgmii_initialize)match->data; 714 sgmii_pdev = to_platform_device(dev);
715 } else {
716 const struct of_device_id *match;
717 struct device_node *np;
718
719 np = of_parse_phandle(pdev->dev.of_node, "internal-phy", 0);
720 if (!np) {
721 dev_err(&pdev->dev, "missing internal-phy property\n");
722 return -ENODEV;
723 }
724
725 sgmii_pdev = of_find_device_by_node(np);
726 if (!sgmii_pdev) {
727 dev_err(&pdev->dev, "invalid internal-phy property\n");
728 return -ENODEV;
729 }
730
731 match = of_match_device(emac_sgmii_dt_match, &sgmii_pdev->dev);
732 if (!match) {
733 dev_err(&pdev->dev, "unrecognized internal phy node\n");
734 ret = -ENODEV;
735 goto error_put_device;
736 }
737
738 phy->initialize = (emac_sgmii_initialize)match->data;
739 }
706 740
707 /* Base address is the first address */ 741 /* Base address is the first address */
708 res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 0); 742 res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 551df1c52620..9bf3b2b82e95 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -22,6 +22,7 @@
22#include <linux/of_device.h> 22#include <linux/of_device.h>
23#include <linux/phy.h> 23#include <linux/phy.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/acpi.h>
25#include "emac.h" 26#include "emac.h"
26#include "emac-mac.h" 27#include "emac-mac.h"
27#include "emac-phy.h" 28#include "emac-phy.h"
@@ -575,6 +576,16 @@ static const struct of_device_id emac_dt_match[] = {
575 {} 576 {}
576}; 577};
577 578
579#if IS_ENABLED(CONFIG_ACPI)
580static const struct acpi_device_id emac_acpi_match[] = {
581 {
582 .id = "QCOM8070",
583 },
584 {}
585};
586MODULE_DEVICE_TABLE(acpi, emac_acpi_match);
587#endif
588
578static int emac_probe(struct platform_device *pdev) 589static int emac_probe(struct platform_device *pdev)
579{ 590{
580 struct net_device *netdev; 591 struct net_device *netdev;
@@ -734,6 +745,7 @@ static struct platform_driver emac_platform_driver = {
734 .driver = { 745 .driver = {
735 .name = "qcom-emac", 746 .name = "qcom-emac",
736 .of_match_table = emac_dt_match, 747 .of_match_table = emac_dt_match,
748 .acpi_match_table = ACPI_PTR(emac_acpi_match),
737 }, 749 },
738}; 750};
739 751