Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Feng Kan and committed by
David S. Miller
de7b5b3d 1fcf77c8

+154 -48
+74 -28
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
··· 593 593 if (!xgene_ring_mgr_init(pdata)) 594 594 return -ENODEV; 595 595 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 + } 600 602 xgene_enet_config_ring_if_assoc(pdata); 601 603 602 604 /* Enable auto-incr for scanning */ ··· 665 663 struct phy_device *phy_dev; 666 664 struct device *dev = &pdata->pdev->dev; 667 665 668 - phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0); 669 - if (!phy_np) { 670 - netdev_dbg(ndev, "No phy-handle found\n"); 671 - return -ENODEV; 666 + if (dev->of_node) { 667 + phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0); 668 + if (!phy_np) { 669 + netdev_dbg(ndev, "No phy-handle found in DT\n"); 670 + return -ENODEV; 671 + } 672 + pdata->phy_dev = of_phy_find_device(phy_np); 672 673 } 673 674 674 - phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link, 675 - 0, pdata->phy_mode); 676 - if (!phy_dev) { 675 + phy_dev = pdata->phy_dev; 676 + 677 + if (!phy_dev || 678 + phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link, 679 + pdata->phy_mode)) { 677 680 netdev_err(ndev, "Could not connect to PHY\n"); 678 681 return -ENODEV; 679 682 } ··· 688 681 ~SUPPORTED_100baseT_Half & 689 682 ~SUPPORTED_1000baseT_Half; 690 683 phy_dev->advertising = phy_dev->supported; 691 - pdata->phy_dev = phy_dev; 692 684 693 685 return 0; 686 + } 687 + 688 + static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata, 689 + struct mii_bus *mdio) 690 + { 691 + struct device *dev = &pdata->pdev->dev; 692 + struct net_device *ndev = pdata->ndev; 693 + struct phy_device *phy; 694 + struct device_node *child_np; 695 + struct device_node *mdio_np = NULL; 696 + int ret; 697 + u32 phy_id; 698 + 699 + if (dev->of_node) { 700 + for_each_child_of_node(dev->of_node, child_np) { 701 + if (of_device_is_compatible(child_np, 702 + "apm,xgene-mdio")) { 703 + mdio_np = child_np; 704 + break; 705 + } 706 + } 707 + 708 + if (!mdio_np) { 709 + netdev_dbg(ndev, "No mdio node in the dts\n"); 710 + return -ENXIO; 711 + } 712 + 713 + return of_mdiobus_register(mdio, mdio_np); 714 + } 715 + 716 + /* Mask out all PHYs from auto probing. */ 717 + mdio->phy_mask = ~0; 718 + 719 + /* Register the MDIO bus */ 720 + ret = mdiobus_register(mdio); 721 + if (ret) 722 + return ret; 723 + 724 + ret = device_property_read_u32(dev, "phy-channel", &phy_id); 725 + if (ret) 726 + ret = device_property_read_u32(dev, "phy-addr", &phy_id); 727 + if (ret) 728 + return -EINVAL; 729 + 730 + phy = get_phy_device(mdio, phy_id, true); 731 + if (!phy || IS_ERR(phy)) 732 + return -EIO; 733 + 734 + ret = phy_device_register(phy); 735 + if (ret) 736 + phy_device_free(phy); 737 + else 738 + pdata->phy_dev = phy; 739 + 740 + return ret; 694 741 } 695 742 696 743 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata) 697 744 { 698 745 struct net_device *ndev = pdata->ndev; 699 - struct device *dev = &pdata->pdev->dev; 700 - struct device_node *child_np; 701 - struct device_node *mdio_np = NULL; 702 746 struct mii_bus *mdio_bus; 703 747 int ret; 704 - 705 - for_each_child_of_node(dev->of_node, child_np) { 706 - if (of_device_is_compatible(child_np, "apm,xgene-mdio")) { 707 - mdio_np = child_np; 708 - break; 709 - } 710 - } 711 - 712 - if (!mdio_np) { 713 - netdev_dbg(ndev, "No mdio node in the dts\n"); 714 - return -ENXIO; 715 - } 716 748 717 749 mdio_bus = mdiobus_alloc(); 718 750 if (!mdio_bus) ··· 766 720 mdio_bus->priv = pdata; 767 721 mdio_bus->parent = &ndev->dev; 768 722 769 - ret = of_mdiobus_register(mdio_bus, mdio_np); 723 + ret = xgene_mdiobus_register(pdata, mdio_bus); 770 724 if (ret) { 771 725 netdev_err(ndev, "Failed to register MDIO bus\n"); 772 726 mdiobus_free(mdio_bus);
+77 -20
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
··· 24 24 #include "xgene_enet_sgmac.h" 25 25 #include "xgene_enet_xgmac.h" 26 26 27 + #define RES_ENET_CSR 0 28 + #define RES_RING_CSR 1 29 + #define RES_RING_CMD 2 30 + 27 31 static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool) 28 32 { 29 33 struct xgene_enet_raw_desc16 *raw_desc; ··· 750 746 .ndo_set_mac_address = xgene_enet_set_mac_address, 751 747 }; 752 748 749 + static int xgene_get_mac_address(struct device *dev, 750 + unsigned char *addr) 751 + { 752 + int ret; 753 + 754 + ret = device_property_read_u8_array(dev, "local-mac-address", addr, 6); 755 + if (ret) 756 + ret = device_property_read_u8_array(dev, "mac-address", 757 + addr, 6); 758 + if (ret) 759 + return -ENODEV; 760 + 761 + return ETH_ALEN; 762 + } 763 + 764 + static int xgene_get_phy_mode(struct device *dev) 765 + { 766 + int i, ret; 767 + char *modestr; 768 + 769 + ret = device_property_read_string(dev, "phy-connection-type", 770 + (const char **)&modestr); 771 + if (ret) 772 + ret = device_property_read_string(dev, "phy-mode", 773 + (const char **)&modestr); 774 + if (ret) 775 + return -ENODEV; 776 + 777 + for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) { 778 + if (!strcasecmp(modestr, phy_modes(i))) 779 + return i; 780 + } 781 + return -ENODEV; 782 + } 783 + 753 784 static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) 754 785 { 755 786 struct platform_device *pdev; ··· 792 753 struct device *dev; 793 754 struct resource *res; 794 755 void __iomem *base_addr; 795 - const char *mac; 796 756 int ret; 797 757 798 758 pdev = pdata->pdev; 799 759 dev = &pdev->dev; 800 760 ndev = pdata->ndev; 801 761 802 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr"); 803 - pdata->base_addr = devm_ioremap_resource(dev, res); 762 + res = platform_get_resource(pdev, IORESOURCE_MEM, RES_ENET_CSR); 763 + if (!res) { 764 + dev_err(dev, "Resource enet_csr not defined\n"); 765 + return -ENODEV; 766 + } 767 + pdata->base_addr = devm_ioremap(dev, res->start, resource_size(res)); 804 768 if (IS_ERR(pdata->base_addr)) { 805 769 dev_err(dev, "Unable to retrieve ENET Port CSR region\n"); 806 770 return PTR_ERR(pdata->base_addr); 807 771 } 808 772 809 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr"); 810 - pdata->ring_csr_addr = devm_ioremap_resource(dev, res); 773 + res = platform_get_resource(pdev, IORESOURCE_MEM, RES_RING_CSR); 774 + if (!res) { 775 + dev_err(dev, "Resource ring_csr not defined\n"); 776 + return -ENODEV; 777 + } 778 + pdata->ring_csr_addr = devm_ioremap(dev, res->start, 779 + resource_size(res)); 811 780 if (IS_ERR(pdata->ring_csr_addr)) { 812 781 dev_err(dev, "Unable to retrieve ENET Ring CSR region\n"); 813 782 return PTR_ERR(pdata->ring_csr_addr); 814 783 } 815 784 816 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd"); 817 - pdata->ring_cmd_addr = devm_ioremap_resource(dev, res); 785 + res = platform_get_resource(pdev, IORESOURCE_MEM, RES_RING_CMD); 786 + if (!res) { 787 + dev_err(dev, "Resource ring_cmd not defined\n"); 788 + return -ENODEV; 789 + } 790 + pdata->ring_cmd_addr = devm_ioremap(dev, res->start, 791 + resource_size(res)); 818 792 if (IS_ERR(pdata->ring_cmd_addr)) { 819 793 dev_err(dev, "Unable to retrieve ENET Ring command region\n"); 820 794 return PTR_ERR(pdata->ring_cmd_addr); ··· 841 789 } 842 790 pdata->rx_irq = ret; 843 791 844 - mac = of_get_mac_address(dev->of_node); 845 - if (mac) 846 - memcpy(ndev->dev_addr, mac, ndev->addr_len); 847 - else 792 + if (xgene_get_mac_address(dev, ndev->dev_addr) != ETH_ALEN) 848 793 eth_hw_addr_random(ndev); 794 + 849 795 memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); 850 796 851 - pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node); 797 + pdata->phy_mode = xgene_get_phy_mode(dev); 852 798 if (pdata->phy_mode < 0) { 853 799 dev_err(dev, "Unable to get phy-connection-type\n"); 854 800 return pdata->phy_mode; ··· 859 809 } 860 810 861 811 pdata->clk = devm_clk_get(&pdev->dev, NULL); 862 - ret = IS_ERR(pdata->clk); 863 812 if (IS_ERR(pdata->clk)) { 864 - dev_err(&pdev->dev, "can't get clock\n"); 865 - ret = PTR_ERR(pdata->clk); 866 - return ret; 813 + /* Firmware may have set up the clock already. */ 814 + pdata->clk = NULL; 867 815 } 868 816 869 817 base_addr = pdata->base_addr; ··· 972 924 goto err; 973 925 } 974 926 975 - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 927 + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64)); 976 928 if (ret) { 977 929 netdev_err(ndev, "No usable DMA configuration\n"); 978 930 goto err; ··· 1020 972 return 0; 1021 973 } 1022 974 1023 - static struct of_device_id xgene_enet_match[] = { 975 + #ifdef CONFIG_ACPI 976 + static const struct acpi_device_id xgene_enet_acpi_match[] = { 977 + { "APMC0D05", }, 978 + { } 979 + }; 980 + MODULE_DEVICE_TABLE(acpi, xgene_enet_acpi_match); 981 + #endif 982 + 983 + static struct of_device_id xgene_enet_of_match[] = { 1024 984 {.compatible = "apm,xgene-enet",}, 1025 985 {}, 1026 986 }; 1027 987 1028 - MODULE_DEVICE_TABLE(of, xgene_enet_match); 988 + MODULE_DEVICE_TABLE(of, xgene_enet_of_match); 1029 989 1030 990 static struct platform_driver xgene_enet_driver = { 1031 991 .driver = { 1032 992 .name = "xgene-enet", 1033 - .of_match_table = xgene_enet_match, 993 + .of_match_table = of_match_ptr(xgene_enet_of_match), 994 + .acpi_match_table = ACPI_PTR(xgene_enet_acpi_match), 1034 995 }, 1035 996 .probe = xgene_enet_probe, 1036 997 .remove = xgene_enet_remove,
+3
drivers/net/ethernet/apm/xgene/xgene_enet_main.h
··· 22 22 #ifndef __XGENE_ENET_MAIN_H__ 23 23 #define __XGENE_ENET_MAIN_H__ 24 24 25 + #include <linux/acpi.h> 25 26 #include <linux/clk.h> 27 + #include <linux/efi.h> 28 + #include <linux/io.h> 26 29 #include <linux/of_platform.h> 27 30 #include <linux/of_net.h> 28 31 #include <linux/of_mdio.h>