Skip to content

Commit de7b5b3

Browse files
apmswdavem330
authored andcommitted
net: eth: xgene: change APM X-Gene SoC platform ethernet to support ACPI
This adds support for APM X-Gene ethernet driver to use ACPI table to derive ethernet driver parameter. Signed-off-by: Feng Kan <fkan@apm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 1fcf77c commit de7b5b3

File tree

3 files changed

+150
-44
lines changed

3 files changed

+150
-44
lines changed

drivers/net/ethernet/apm/xgene/xgene_enet_hw.c

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -593,10 +593,12 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
593593
if (!xgene_ring_mgr_init(pdata))
594594
return -ENODEV;
595595

596-
clk_prepare_enable(pdata->clk);
597-
clk_disable_unprepare(pdata->clk);
598-
clk_prepare_enable(pdata->clk);
599-
xgene_enet_ecc_init(pdata);
596+
if (!efi_enabled(EFI_BOOT)) {
597+
clk_prepare_enable(pdata->clk);
598+
clk_disable_unprepare(pdata->clk);
599+
clk_prepare_enable(pdata->clk);
600+
xgene_enet_ecc_init(pdata);
601+
}
600602
xgene_enet_config_ring_if_assoc(pdata);
601603

602604
/* Enable auto-incr for scanning */
@@ -663,15 +665,20 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
663665
struct phy_device *phy_dev;
664666
struct device *dev = &pdata->pdev->dev;
665667

666-
phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0);
667-
if (!phy_np) {
668-
netdev_dbg(ndev, "No phy-handle found\n");
669-
return -ENODEV;
668+
if (dev->of_node) {
669+
phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0);
670+
if (!phy_np) {
671+
netdev_dbg(ndev, "No phy-handle found in DT\n");
672+
return -ENODEV;
673+
}
674+
pdata->phy_dev = of_phy_find_device(phy_np);
670675
}
671676

672-
phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
673-
0, pdata->phy_mode);
674-
if (!phy_dev) {
677+
phy_dev = pdata->phy_dev;
678+
679+
if (!phy_dev ||
680+
phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
681+
pdata->phy_mode)) {
675682
netdev_err(ndev, "Could not connect to PHY\n");
676683
return -ENODEV;
677684
}
@@ -681,32 +688,71 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
681688
~SUPPORTED_100baseT_Half &
682689
~SUPPORTED_1000baseT_Half;
683690
phy_dev->advertising = phy_dev->supported;
684-
pdata->phy_dev = phy_dev;
685691

686692
return 0;
687693
}
688694

689-
int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
695+
static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
696+
struct mii_bus *mdio)
690697
{
691-
struct net_device *ndev = pdata->ndev;
692698
struct device *dev = &pdata->pdev->dev;
699+
struct net_device *ndev = pdata->ndev;
700+
struct phy_device *phy;
693701
struct device_node *child_np;
694702
struct device_node *mdio_np = NULL;
695-
struct mii_bus *mdio_bus;
696703
int ret;
704+
u32 phy_id;
705+
706+
if (dev->of_node) {
707+
for_each_child_of_node(dev->of_node, child_np) {
708+
if (of_device_is_compatible(child_np,
709+
"apm,xgene-mdio")) {
710+
mdio_np = child_np;
711+
break;
712+
}
713+
}
697714

698-
for_each_child_of_node(dev->of_node, child_np) {
699-
if (of_device_is_compatible(child_np, "apm,xgene-mdio")) {
700-
mdio_np = child_np;
701-
break;
715+
if (!mdio_np) {
716+
netdev_dbg(ndev, "No mdio node in the dts\n");
717+
return -ENXIO;
702718
}
703-
}
704719

705-
if (!mdio_np) {
706-
netdev_dbg(ndev, "No mdio node in the dts\n");
707-
return -ENXIO;
720+
return of_mdiobus_register(mdio, mdio_np);
708721
}
709722

723+
/* Mask out all PHYs from auto probing. */
724+
mdio->phy_mask = ~0;
725+
726+
/* Register the MDIO bus */
727+
ret = mdiobus_register(mdio);
728+
if (ret)
729+
return ret;
730+
731+
ret = device_property_read_u32(dev, "phy-channel", &phy_id);
732+
if (ret)
733+
ret = device_property_read_u32(dev, "phy-addr", &phy_id);
734+
if (ret)
735+
return -EINVAL;
736+
737+
phy = get_phy_device(mdio, phy_id, true);
738+
if (!phy || IS_ERR(phy))
739+
return -EIO;
740+
741+
ret = phy_device_register(phy);
742+
if (ret)
743+
phy_device_free(phy);
744+
else
745+
pdata->phy_dev = phy;
746+
747+
return ret;
748+
}
749+
750+
int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
751+
{
752+
struct net_device *ndev = pdata->ndev;
753+
struct mii_bus *mdio_bus;
754+
int ret;
755+
710756
mdio_bus = mdiobus_alloc();
711757
if (!mdio_bus)
712758
return -ENOMEM;
@@ -720,7 +766,7 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
720766
mdio_bus->priv = pdata;
721767
mdio_bus->parent = &ndev->dev;
722768

723-
ret = of_mdiobus_register(mdio_bus, mdio_np);
769+
ret = xgene_mdiobus_register(pdata, mdio_bus);
724770
if (ret) {
725771
netdev_err(ndev, "Failed to register MDIO bus\n");
726772
mdiobus_free(mdio_bus);

drivers/net/ethernet/apm/xgene/xgene_enet_main.c

Lines changed: 77 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
#include "xgene_enet_sgmac.h"
2525
#include "xgene_enet_xgmac.h"
2626

27+
#define RES_ENET_CSR 0
28+
#define RES_RING_CSR 1
29+
#define RES_RING_CMD 2
30+
2731
static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
2832
{
2933
struct xgene_enet_raw_desc16 *raw_desc;
@@ -746,36 +750,84 @@ static const struct net_device_ops xgene_ndev_ops = {
746750
.ndo_set_mac_address = xgene_enet_set_mac_address,
747751
};
748752

753+
static int xgene_get_mac_address(struct device *dev,
754+
unsigned char *addr)
755+
{
756+
int ret;
757+
758+
ret = device_property_read_u8_array(dev, "local-mac-address", addr, 6);
759+
if (ret)
760+
ret = device_property_read_u8_array(dev, "mac-address",
761+
addr, 6);
762+
if (ret)
763+
return -ENODEV;
764+
765+
return ETH_ALEN;
766+
}
767+
768+
static int xgene_get_phy_mode(struct device *dev)
769+
{
770+
int i, ret;
771+
char *modestr;
772+
773+
ret = device_property_read_string(dev, "phy-connection-type",
774+
(const char **)&modestr);
775+
if (ret)
776+
ret = device_property_read_string(dev, "phy-mode",
777+
(const char **)&modestr);
778+
if (ret)
779+
return -ENODEV;
780+
781+
for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
782+
if (!strcasecmp(modestr, phy_modes(i)))
783+
return i;
784+
}
785+
return -ENODEV;
786+
}
787+
749788
static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
750789
{
751790
struct platform_device *pdev;
752791
struct net_device *ndev;
753792
struct device *dev;
754793
struct resource *res;
755794
void __iomem *base_addr;
756-
const char *mac;
757795
int ret;
758796

759797
pdev = pdata->pdev;
760798
dev = &pdev->dev;
761799
ndev = pdata->ndev;
762800

763-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr");
764-
pdata->base_addr = devm_ioremap_resource(dev, res);
801+
res = platform_get_resource(pdev, IORESOURCE_MEM, RES_ENET_CSR);
802+
if (!res) {
803+
dev_err(dev, "Resource enet_csr not defined\n");
804+
return -ENODEV;
805+
}
806+
pdata->base_addr = devm_ioremap(dev, res->start, resource_size(res));
765807
if (IS_ERR(pdata->base_addr)) {
766808
dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
767809
return PTR_ERR(pdata->base_addr);
768810
}
769811

770-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr");
771-
pdata->ring_csr_addr = devm_ioremap_resource(dev, res);
812+
res = platform_get_resource(pdev, IORESOURCE_MEM, RES_RING_CSR);
813+
if (!res) {
814+
dev_err(dev, "Resource ring_csr not defined\n");
815+
return -ENODEV;
816+
}
817+
pdata->ring_csr_addr = devm_ioremap(dev, res->start,
818+
resource_size(res));
772819
if (IS_ERR(pdata->ring_csr_addr)) {
773820
dev_err(dev, "Unable to retrieve ENET Ring CSR region\n");
774821
return PTR_ERR(pdata->ring_csr_addr);
775822
}
776823

777-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd");
778-
pdata->ring_cmd_addr = devm_ioremap_resource(dev, res);
824+
res = platform_get_resource(pdev, IORESOURCE_MEM, RES_RING_CMD);
825+
if (!res) {
826+
dev_err(dev, "Resource ring_cmd not defined\n");
827+
return -ENODEV;
828+
}
829+
pdata->ring_cmd_addr = devm_ioremap(dev, res->start,
830+
resource_size(res));
779831
if (IS_ERR(pdata->ring_cmd_addr)) {
780832
dev_err(dev, "Unable to retrieve ENET Ring command region\n");
781833
return PTR_ERR(pdata->ring_cmd_addr);
@@ -789,14 +841,12 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
789841
}
790842
pdata->rx_irq = ret;
791843

792-
mac = of_get_mac_address(dev->of_node);
793-
if (mac)
794-
memcpy(ndev->dev_addr, mac, ndev->addr_len);
795-
else
844+
if (xgene_get_mac_address(dev, ndev->dev_addr) != ETH_ALEN)
796845
eth_hw_addr_random(ndev);
846+
797847
memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
798848

799-
pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
849+
pdata->phy_mode = xgene_get_phy_mode(dev);
800850
if (pdata->phy_mode < 0) {
801851
dev_err(dev, "Unable to get phy-connection-type\n");
802852
return pdata->phy_mode;
@@ -809,11 +859,9 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
809859
}
810860

811861
pdata->clk = devm_clk_get(&pdev->dev, NULL);
812-
ret = IS_ERR(pdata->clk);
813862
if (IS_ERR(pdata->clk)) {
814-
dev_err(&pdev->dev, "can't get clock\n");
815-
ret = PTR_ERR(pdata->clk);
816-
return ret;
863+
/* Firmware may have set up the clock already. */
864+
pdata->clk = NULL;
817865
}
818866

819867
base_addr = pdata->base_addr;
@@ -924,7 +972,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
924972
goto err;
925973
}
926974

927-
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
975+
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
928976
if (ret) {
929977
netdev_err(ndev, "No usable DMA configuration\n");
930978
goto err;
@@ -972,17 +1020,26 @@ static int xgene_enet_remove(struct platform_device *pdev)
9721020
return 0;
9731021
}
9741022

975-
static struct of_device_id xgene_enet_match[] = {
1023+
#ifdef CONFIG_ACPI
1024+
static const struct acpi_device_id xgene_enet_acpi_match[] = {
1025+
{ "APMC0D05", },
1026+
{ }
1027+
};
1028+
MODULE_DEVICE_TABLE(acpi, xgene_enet_acpi_match);
1029+
#endif
1030+
1031+
static struct of_device_id xgene_enet_of_match[] = {
9761032
{.compatible = "apm,xgene-enet",},
9771033
{},
9781034
};
9791035

980-
MODULE_DEVICE_TABLE(of, xgene_enet_match);
1036+
MODULE_DEVICE_TABLE(of, xgene_enet_of_match);
9811037

9821038
static struct platform_driver xgene_enet_driver = {
9831039
.driver = {
9841040
.name = "xgene-enet",
985-
.of_match_table = xgene_enet_match,
1041+
.of_match_table = of_match_ptr(xgene_enet_of_match),
1042+
.acpi_match_table = ACPI_PTR(xgene_enet_acpi_match),
9861043
},
9871044
.probe = xgene_enet_probe,
9881045
.remove = xgene_enet_remove,

drivers/net/ethernet/apm/xgene/xgene_enet_main.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@
2222
#ifndef __XGENE_ENET_MAIN_H__
2323
#define __XGENE_ENET_MAIN_H__
2424

25+
#include <linux/acpi.h>
2526
#include <linux/clk.h>
27+
#include <linux/efi.h>
28+
#include <linux/io.h>
2629
#include <linux/of_platform.h>
2730
#include <linux/of_net.h>
2831
#include <linux/of_mdio.h>

0 commit comments

Comments
 (0)