diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-10-03 14:12:57 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-10-09 12:12:18 -0400 |
commit | 49cb1f718360f86075341e35fad57748a5c182f9 (patch) | |
tree | a152a34ceb473a23b21763f8dbe9ea3011109550 | |
parent | ab7ea3053575f31264bc8b8357203bdf970a6248 (diff) |
PCI: mvebu: Move port parsing and resource claiming to separate function
Move the PCIe port parsing and resource claiming to a separate function in
preparation to add proper cleanup of claimed resources.
Tested-by: Willy Tarreau <w@1wt.eu> (Iomega iConnect Kirkwood, MiraBox Armada 370)
Tested-by: Andrew Lunn <andrew@lunn.ch> (D-Link DIR664 Kirkwood)
Tested-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> (Armada XP GP)
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 130 |
1 files changed, 74 insertions, 56 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 19144ed7bdad..13ab0350f7fb 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -928,6 +928,76 @@ static int mvebu_pcie_resume(struct device *dev) | |||
928 | return 0; | 928 | return 0; |
929 | } | 929 | } |
930 | 930 | ||
931 | static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, | ||
932 | struct mvebu_pcie_port *port, struct device_node *child) | ||
933 | { | ||
934 | struct device *dev = &pcie->pdev->dev; | ||
935 | enum of_gpio_flags flags; | ||
936 | int ret; | ||
937 | |||
938 | port->pcie = pcie; | ||
939 | |||
940 | if (of_property_read_u32(child, "marvell,pcie-port", &port->port)) { | ||
941 | dev_warn(dev, "ignoring %s, missing pcie-port property\n", | ||
942 | of_node_full_name(child)); | ||
943 | goto skip; | ||
944 | } | ||
945 | |||
946 | if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane)) | ||
947 | port->lane = 0; | ||
948 | |||
949 | port->name = kasprintf(GFP_KERNEL, "pcie%d.%d", port->port, port->lane); | ||
950 | |||
951 | port->devfn = of_pci_get_devfn(child); | ||
952 | if (port->devfn < 0) | ||
953 | goto skip; | ||
954 | |||
955 | ret = mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_MEM, | ||
956 | &port->mem_target, &port->mem_attr); | ||
957 | if (ret < 0) { | ||
958 | dev_err(dev, "%s: cannot get tgt/attr for mem window\n", | ||
959 | port->name); | ||
960 | goto skip; | ||
961 | } | ||
962 | |||
963 | if (resource_size(&pcie->io) != 0) | ||
964 | mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_IO, | ||
965 | &port->io_target, &port->io_attr); | ||
966 | else { | ||
967 | port->io_target = -1; | ||
968 | port->io_attr = -1; | ||
969 | } | ||
970 | |||
971 | port->reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, | ||
972 | &flags); | ||
973 | if (gpio_is_valid(port->reset_gpio)) { | ||
974 | port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
975 | port->reset_name = kasprintf(GFP_KERNEL, "%s-reset", | ||
976 | port->name); | ||
977 | |||
978 | ret = devm_gpio_request_one(dev, port->reset_gpio, | ||
979 | GPIOF_DIR_OUT, port->reset_name); | ||
980 | if (ret) { | ||
981 | if (ret == -EPROBE_DEFER) | ||
982 | goto err; | ||
983 | goto skip; | ||
984 | } | ||
985 | } | ||
986 | |||
987 | port->clk = of_clk_get_by_name(child, NULL); | ||
988 | if (IS_ERR(port->clk)) { | ||
989 | dev_err(dev, "%s: cannot get clock\n", port->name); | ||
990 | goto skip; | ||
991 | } | ||
992 | |||
993 | return 1; | ||
994 | |||
995 | skip: | ||
996 | ret = 0; | ||
997 | err: | ||
998 | return ret; | ||
999 | } | ||
1000 | |||
931 | static int mvebu_pcie_probe(struct platform_device *pdev) | 1001 | static int mvebu_pcie_probe(struct platform_device *pdev) |
932 | { | 1002 | { |
933 | struct mvebu_pcie *pcie; | 1003 | struct mvebu_pcie *pcie; |
@@ -980,76 +1050,24 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
980 | i = 0; | 1050 | i = 0; |
981 | for_each_available_child_of_node(pdev->dev.of_node, child) { | 1051 | for_each_available_child_of_node(pdev->dev.of_node, child) { |
982 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 1052 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
983 | enum of_gpio_flags flags; | ||
984 | |||
985 | port->pcie = pcie; | ||
986 | 1053 | ||
987 | if (of_property_read_u32(child, "marvell,pcie-port", | 1054 | ret = mvebu_pcie_parse_port(pcie, port, child); |
988 | &port->port)) { | 1055 | if (ret < 0) |
989 | dev_warn(&pdev->dev, | 1056 | return ret; |
990 | "ignoring %s, missing pcie-port property\n", | 1057 | else if (ret == 0) |
991 | of_node_full_name(child)); | ||
992 | continue; | 1058 | continue; |
993 | } | ||
994 | 1059 | ||
995 | if (of_property_read_u32(child, "marvell,pcie-lane", | ||
996 | &port->lane)) | ||
997 | port->lane = 0; | ||
998 | |||
999 | port->name = kasprintf(GFP_KERNEL, "pcie%d.%d", | ||
1000 | port->port, port->lane); | ||
1001 | |||
1002 | port->devfn = of_pci_get_devfn(child); | ||
1003 | if (port->devfn < 0) | ||
1004 | continue; | ||
1005 | |||
1006 | ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_MEM, | ||
1007 | &port->mem_target, &port->mem_attr); | ||
1008 | if (ret < 0) { | ||
1009 | dev_err(&pdev->dev, "%s: cannot get tgt/attr for mem window\n", | ||
1010 | port->name); | ||
1011 | continue; | ||
1012 | } | ||
1013 | |||
1014 | if (resource_size(&pcie->io) != 0) | ||
1015 | mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, | ||
1016 | &port->io_target, &port->io_attr); | ||
1017 | else { | ||
1018 | port->io_target = -1; | ||
1019 | port->io_attr = -1; | ||
1020 | } | ||
1021 | |||
1022 | port->reset_gpio = of_get_named_gpio_flags(child, | ||
1023 | "reset-gpios", 0, &flags); | ||
1024 | if (gpio_is_valid(port->reset_gpio)) { | 1060 | if (gpio_is_valid(port->reset_gpio)) { |
1025 | u32 reset_udelay = 20000; | 1061 | u32 reset_udelay = 20000; |
1026 | 1062 | ||
1027 | port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
1028 | port->reset_name = kasprintf(GFP_KERNEL, "%s-reset", | ||
1029 | port->name); | ||
1030 | of_property_read_u32(child, "reset-delay-us", | 1063 | of_property_read_u32(child, "reset-delay-us", |
1031 | &reset_udelay); | 1064 | &reset_udelay); |
1032 | 1065 | ||
1033 | ret = devm_gpio_request_one(&pdev->dev, | ||
1034 | port->reset_gpio, GPIOF_DIR_OUT, port->reset_name); | ||
1035 | if (ret) { | ||
1036 | if (ret == -EPROBE_DEFER) | ||
1037 | return ret; | ||
1038 | continue; | ||
1039 | } | ||
1040 | |||
1041 | gpio_set_value(port->reset_gpio, | 1066 | gpio_set_value(port->reset_gpio, |
1042 | (port->reset_active_low) ? 1 : 0); | 1067 | (port->reset_active_low) ? 1 : 0); |
1043 | msleep(reset_udelay/1000); | 1068 | msleep(reset_udelay/1000); |
1044 | } | 1069 | } |
1045 | 1070 | ||
1046 | port->clk = of_clk_get_by_name(child, NULL); | ||
1047 | if (IS_ERR(port->clk)) { | ||
1048 | dev_err(&pdev->dev, "%s: cannot get clock\n", | ||
1049 | port->name); | ||
1050 | continue; | ||
1051 | } | ||
1052 | |||
1053 | ret = clk_prepare_enable(port->clk); | 1071 | ret = clk_prepare_enable(port->clk); |
1054 | if (ret) | 1072 | if (ret) |
1055 | continue; | 1073 | continue; |