.. | .. |
---|
15 | 15 | #include <linux/irqdomain.h> |
---|
16 | 16 | #include <linux/kernel.h> |
---|
17 | 17 | #include <linux/msi.h> |
---|
| 18 | +#include <linux/module.h> |
---|
18 | 19 | #include <linux/of_address.h> |
---|
19 | 20 | #include <linux/of_pci.h> |
---|
20 | 21 | #include <linux/of_platform.h> |
---|
.. | .. |
---|
90 | 91 | #define AHB2PCIE_SIZE(x) ((x) & GENMASK(4, 0)) |
---|
91 | 92 | #define PCIE_AXI_WINDOW0 0x448 |
---|
92 | 93 | #define WIN_ENABLE BIT(7) |
---|
| 94 | +/* |
---|
| 95 | + * Define PCIe to AHB window size as 2^33 to support max 8GB address space |
---|
| 96 | + * translate, support least 4GB DRAM size access from EP DMA(physical DRAM |
---|
| 97 | + * start from 0x40000000). |
---|
| 98 | + */ |
---|
| 99 | +#define PCIE2AHB_SIZE 0x21 |
---|
93 | 100 | |
---|
94 | 101 | /* PCIe V2 configuration transaction header */ |
---|
95 | 102 | #define PCIE_CFG_HEADER0 0x460 |
---|
.. | .. |
---|
165 | 172 | * @obff_ck: pointer to OBFF functional block operating clock |
---|
166 | 173 | * @pipe_ck: pointer to LTSSM and PHY/MAC layer operating clock |
---|
167 | 174 | * @phy: pointer to PHY control block |
---|
168 | | - * @lane: lane count |
---|
169 | 175 | * @slot: port slot |
---|
| 176 | + * @irq: GIC irq |
---|
170 | 177 | * @irq_domain: legacy INTx IRQ domain |
---|
171 | 178 | * @inner_domain: inner IRQ domain |
---|
172 | 179 | * @msi_domain: MSI IRQ domain |
---|
.. | .. |
---|
185 | 192 | struct clk *obff_ck; |
---|
186 | 193 | struct clk *pipe_ck; |
---|
187 | 194 | struct phy *phy; |
---|
188 | | - u32 lane; |
---|
189 | 195 | u32 slot; |
---|
| 196 | + int irq; |
---|
190 | 197 | struct irq_domain *irq_domain; |
---|
191 | 198 | struct irq_domain *inner_domain; |
---|
192 | 199 | struct irq_domain *msi_domain; |
---|
.. | .. |
---|
199 | 206 | * @dev: pointer to PCIe device |
---|
200 | 207 | * @base: IO mapped register base |
---|
201 | 208 | * @free_ck: free-run reference clock |
---|
202 | | - * @io: IO resource |
---|
203 | | - * @pio: PIO resource |
---|
204 | 209 | * @mem: non-prefetchable memory resource |
---|
205 | | - * @busn: bus range |
---|
206 | | - * @offset: IO / Memory offset |
---|
207 | 210 | * @ports: pointer to PCIe port information |
---|
208 | 211 | * @soc: pointer to SoC-dependent operations |
---|
209 | 212 | */ |
---|
.. | .. |
---|
212 | 215 | void __iomem *base; |
---|
213 | 216 | struct clk *free_ck; |
---|
214 | 217 | |
---|
215 | | - struct resource io; |
---|
216 | | - struct resource pio; |
---|
217 | | - struct resource mem; |
---|
218 | | - struct resource busn; |
---|
219 | | - struct { |
---|
220 | | - resource_size_t mem; |
---|
221 | | - resource_size_t io; |
---|
222 | | - } offset; |
---|
223 | 218 | struct list_head ports; |
---|
224 | 219 | const struct mtk_pcie_soc *soc; |
---|
225 | 220 | }; |
---|
.. | .. |
---|
230 | 225 | |
---|
231 | 226 | clk_disable_unprepare(pcie->free_ck); |
---|
232 | 227 | |
---|
233 | | - if (dev->pm_domain) { |
---|
234 | | - pm_runtime_put_sync(dev); |
---|
235 | | - pm_runtime_disable(dev); |
---|
236 | | - } |
---|
| 228 | + pm_runtime_put_sync(dev); |
---|
| 229 | + pm_runtime_disable(dev); |
---|
237 | 230 | } |
---|
238 | 231 | |
---|
239 | 232 | static void mtk_pcie_port_free(struct mtk_pcie_port *port) |
---|
.. | .. |
---|
537 | 530 | writel(val, port->base + PCIE_INT_MASK); |
---|
538 | 531 | } |
---|
539 | 532 | |
---|
| 533 | +static void mtk_pcie_irq_teardown(struct mtk_pcie *pcie) |
---|
| 534 | +{ |
---|
| 535 | + struct mtk_pcie_port *port, *tmp; |
---|
| 536 | + |
---|
| 537 | + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { |
---|
| 538 | + irq_set_chained_handler_and_data(port->irq, NULL, NULL); |
---|
| 539 | + |
---|
| 540 | + if (port->irq_domain) |
---|
| 541 | + irq_domain_remove(port->irq_domain); |
---|
| 542 | + |
---|
| 543 | + if (IS_ENABLED(CONFIG_PCI_MSI)) { |
---|
| 544 | + if (port->msi_domain) |
---|
| 545 | + irq_domain_remove(port->msi_domain); |
---|
| 546 | + if (port->inner_domain) |
---|
| 547 | + irq_domain_remove(port->inner_domain); |
---|
| 548 | + } |
---|
| 549 | + |
---|
| 550 | + irq_dispose_mapping(port->irq); |
---|
| 551 | + } |
---|
| 552 | +} |
---|
| 553 | + |
---|
540 | 554 | static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq, |
---|
541 | 555 | irq_hw_number_t hwirq) |
---|
542 | 556 | { |
---|
.. | .. |
---|
566 | 580 | |
---|
567 | 581 | port->irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, |
---|
568 | 582 | &intx_domain_ops, port); |
---|
| 583 | + of_node_put(pcie_intc_node); |
---|
569 | 584 | if (!port->irq_domain) { |
---|
570 | 585 | dev_err(dev, "failed to get INTx IRQ domain\n"); |
---|
571 | 586 | return -ENODEV; |
---|
.. | .. |
---|
617 | 632 | } |
---|
618 | 633 | |
---|
619 | 634 | chained_irq_exit(irqchip, desc); |
---|
620 | | - |
---|
621 | | - return; |
---|
622 | 635 | } |
---|
623 | 636 | |
---|
624 | 637 | static int mtk_pcie_setup_irq(struct mtk_pcie_port *port, |
---|
.. | .. |
---|
627 | 640 | struct mtk_pcie *pcie = port->pcie; |
---|
628 | 641 | struct device *dev = pcie->dev; |
---|
629 | 642 | struct platform_device *pdev = to_platform_device(dev); |
---|
630 | | - int err, irq; |
---|
| 643 | + int err; |
---|
631 | 644 | |
---|
632 | 645 | err = mtk_pcie_init_irq_domain(port, node); |
---|
633 | 646 | if (err) { |
---|
.. | .. |
---|
635 | 648 | return err; |
---|
636 | 649 | } |
---|
637 | 650 | |
---|
638 | | - irq = platform_get_irq(pdev, port->slot); |
---|
639 | | - irq_set_chained_handler_and_data(irq, mtk_pcie_intr_handler, port); |
---|
| 651 | + port->irq = platform_get_irq(pdev, port->slot); |
---|
| 652 | + if (port->irq < 0) |
---|
| 653 | + return port->irq; |
---|
| 654 | + |
---|
| 655 | + irq_set_chained_handler_and_data(port->irq, |
---|
| 656 | + mtk_pcie_intr_handler, port); |
---|
640 | 657 | |
---|
641 | 658 | return 0; |
---|
642 | 659 | } |
---|
.. | .. |
---|
644 | 661 | static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port) |
---|
645 | 662 | { |
---|
646 | 663 | struct mtk_pcie *pcie = port->pcie; |
---|
647 | | - struct resource *mem = &pcie->mem; |
---|
| 664 | + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); |
---|
| 665 | + struct resource *mem = NULL; |
---|
| 666 | + struct resource_entry *entry; |
---|
648 | 667 | const struct mtk_pcie_soc *soc = port->pcie->soc; |
---|
649 | 668 | u32 val; |
---|
650 | | - size_t size; |
---|
651 | 669 | int err; |
---|
| 670 | + |
---|
| 671 | + entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); |
---|
| 672 | + if (entry) |
---|
| 673 | + mem = entry->res; |
---|
| 674 | + if (!mem) |
---|
| 675 | + return -EINVAL; |
---|
652 | 676 | |
---|
653 | 677 | /* MT7622 platforms need to enable LTSSM and ASPM from PCIe subsys */ |
---|
654 | 678 | if (pcie->base) { |
---|
.. | .. |
---|
702 | 726 | mtk_pcie_enable_msi(port); |
---|
703 | 727 | |
---|
704 | 728 | /* Set AHB to PCIe translation windows */ |
---|
705 | | - size = mem->end - mem->start; |
---|
706 | | - val = lower_32_bits(mem->start) | AHB2PCIE_SIZE(fls(size)); |
---|
| 729 | + val = lower_32_bits(mem->start) | |
---|
| 730 | + AHB2PCIE_SIZE(fls(resource_size(mem))); |
---|
707 | 731 | writel(val, port->base + PCIE_AHB_TRANS_BASE0_L); |
---|
708 | 732 | |
---|
709 | 733 | val = upper_32_bits(mem->start); |
---|
710 | 734 | writel(val, port->base + PCIE_AHB_TRANS_BASE0_H); |
---|
711 | 735 | |
---|
712 | 736 | /* Set PCIe to AXI translation memory space.*/ |
---|
713 | | - val = fls(0xffffffff) | WIN_ENABLE; |
---|
| 737 | + val = PCIE2AHB_SIZE | WIN_ENABLE; |
---|
714 | 738 | writel(val, port->base + PCIE_AXI_WINDOW0); |
---|
715 | 739 | |
---|
716 | 740 | return 0; |
---|
.. | .. |
---|
879 | 903 | int slot) |
---|
880 | 904 | { |
---|
881 | 905 | struct mtk_pcie_port *port; |
---|
882 | | - struct resource *regs; |
---|
883 | 906 | struct device *dev = pcie->dev; |
---|
884 | 907 | struct platform_device *pdev = to_platform_device(dev); |
---|
885 | 908 | char name[10]; |
---|
.. | .. |
---|
889 | 912 | if (!port) |
---|
890 | 913 | return -ENOMEM; |
---|
891 | 914 | |
---|
892 | | - err = of_property_read_u32(node, "num-lanes", &port->lane); |
---|
893 | | - if (err) { |
---|
894 | | - dev_err(dev, "missing num-lanes property\n"); |
---|
895 | | - return err; |
---|
896 | | - } |
---|
897 | | - |
---|
898 | 915 | snprintf(name, sizeof(name), "port%d", slot); |
---|
899 | | - regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); |
---|
900 | | - port->base = devm_ioremap_resource(dev, regs); |
---|
| 916 | + port->base = devm_platform_ioremap_resource_byname(pdev, name); |
---|
901 | 917 | if (IS_ERR(port->base)) { |
---|
902 | 918 | dev_err(dev, "failed to map port%d base\n", slot); |
---|
903 | 919 | return PTR_ERR(port->base); |
---|
.. | .. |
---|
912 | 928 | |
---|
913 | 929 | /* sys_ck might be divided into the following parts in some chips */ |
---|
914 | 930 | snprintf(name, sizeof(name), "ahb_ck%d", slot); |
---|
915 | | - port->ahb_ck = devm_clk_get(dev, name); |
---|
916 | | - if (IS_ERR(port->ahb_ck)) { |
---|
917 | | - if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER) |
---|
918 | | - return -EPROBE_DEFER; |
---|
919 | | - |
---|
920 | | - port->ahb_ck = NULL; |
---|
921 | | - } |
---|
| 931 | + port->ahb_ck = devm_clk_get_optional(dev, name); |
---|
| 932 | + if (IS_ERR(port->ahb_ck)) |
---|
| 933 | + return PTR_ERR(port->ahb_ck); |
---|
922 | 934 | |
---|
923 | 935 | snprintf(name, sizeof(name), "axi_ck%d", slot); |
---|
924 | | - port->axi_ck = devm_clk_get(dev, name); |
---|
925 | | - if (IS_ERR(port->axi_ck)) { |
---|
926 | | - if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER) |
---|
927 | | - return -EPROBE_DEFER; |
---|
928 | | - |
---|
929 | | - port->axi_ck = NULL; |
---|
930 | | - } |
---|
| 936 | + port->axi_ck = devm_clk_get_optional(dev, name); |
---|
| 937 | + if (IS_ERR(port->axi_ck)) |
---|
| 938 | + return PTR_ERR(port->axi_ck); |
---|
931 | 939 | |
---|
932 | 940 | snprintf(name, sizeof(name), "aux_ck%d", slot); |
---|
933 | | - port->aux_ck = devm_clk_get(dev, name); |
---|
934 | | - if (IS_ERR(port->aux_ck)) { |
---|
935 | | - if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER) |
---|
936 | | - return -EPROBE_DEFER; |
---|
937 | | - |
---|
938 | | - port->aux_ck = NULL; |
---|
939 | | - } |
---|
| 941 | + port->aux_ck = devm_clk_get_optional(dev, name); |
---|
| 942 | + if (IS_ERR(port->aux_ck)) |
---|
| 943 | + return PTR_ERR(port->aux_ck); |
---|
940 | 944 | |
---|
941 | 945 | snprintf(name, sizeof(name), "obff_ck%d", slot); |
---|
942 | | - port->obff_ck = devm_clk_get(dev, name); |
---|
943 | | - if (IS_ERR(port->obff_ck)) { |
---|
944 | | - if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER) |
---|
945 | | - return -EPROBE_DEFER; |
---|
946 | | - |
---|
947 | | - port->obff_ck = NULL; |
---|
948 | | - } |
---|
| 946 | + port->obff_ck = devm_clk_get_optional(dev, name); |
---|
| 947 | + if (IS_ERR(port->obff_ck)) |
---|
| 948 | + return PTR_ERR(port->obff_ck); |
---|
949 | 949 | |
---|
950 | 950 | snprintf(name, sizeof(name), "pipe_ck%d", slot); |
---|
951 | | - port->pipe_ck = devm_clk_get(dev, name); |
---|
952 | | - if (IS_ERR(port->pipe_ck)) { |
---|
953 | | - if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER) |
---|
954 | | - return -EPROBE_DEFER; |
---|
955 | | - |
---|
956 | | - port->pipe_ck = NULL; |
---|
957 | | - } |
---|
| 951 | + port->pipe_ck = devm_clk_get_optional(dev, name); |
---|
| 952 | + if (IS_ERR(port->pipe_ck)) |
---|
| 953 | + return PTR_ERR(port->pipe_ck); |
---|
958 | 954 | |
---|
959 | 955 | snprintf(name, sizeof(name), "pcie-rst%d", slot); |
---|
960 | 956 | port->reset = devm_reset_control_get_optional_exclusive(dev, name); |
---|
.. | .. |
---|
1007 | 1003 | pcie->free_ck = NULL; |
---|
1008 | 1004 | } |
---|
1009 | 1005 | |
---|
1010 | | - if (dev->pm_domain) { |
---|
1011 | | - pm_runtime_enable(dev); |
---|
1012 | | - pm_runtime_get_sync(dev); |
---|
1013 | | - } |
---|
| 1006 | + pm_runtime_enable(dev); |
---|
| 1007 | + pm_runtime_get_sync(dev); |
---|
1014 | 1008 | |
---|
1015 | 1009 | /* enable top level clock */ |
---|
1016 | 1010 | err = clk_prepare_enable(pcie->free_ck); |
---|
.. | .. |
---|
1022 | 1016 | return 0; |
---|
1023 | 1017 | |
---|
1024 | 1018 | err_free_ck: |
---|
1025 | | - if (dev->pm_domain) { |
---|
1026 | | - pm_runtime_put_sync(dev); |
---|
1027 | | - pm_runtime_disable(dev); |
---|
1028 | | - } |
---|
| 1019 | + pm_runtime_put_sync(dev); |
---|
| 1020 | + pm_runtime_disable(dev); |
---|
1029 | 1021 | |
---|
1030 | 1022 | return err; |
---|
1031 | 1023 | } |
---|
.. | .. |
---|
1034 | 1026 | { |
---|
1035 | 1027 | struct device *dev = pcie->dev; |
---|
1036 | 1028 | struct device_node *node = dev->of_node, *child; |
---|
1037 | | - struct of_pci_range_parser parser; |
---|
1038 | | - struct of_pci_range range; |
---|
1039 | | - struct resource res; |
---|
1040 | 1029 | struct mtk_pcie_port *port, *tmp; |
---|
1041 | 1030 | int err; |
---|
1042 | | - |
---|
1043 | | - if (of_pci_range_parser_init(&parser, node)) { |
---|
1044 | | - dev_err(dev, "missing \"ranges\" property\n"); |
---|
1045 | | - return -EINVAL; |
---|
1046 | | - } |
---|
1047 | | - |
---|
1048 | | - for_each_of_pci_range(&parser, &range) { |
---|
1049 | | - err = of_pci_range_to_resource(&range, node, &res); |
---|
1050 | | - if (err < 0) |
---|
1051 | | - return err; |
---|
1052 | | - |
---|
1053 | | - switch (res.flags & IORESOURCE_TYPE_BITS) { |
---|
1054 | | - case IORESOURCE_IO: |
---|
1055 | | - pcie->offset.io = res.start - range.pci_addr; |
---|
1056 | | - |
---|
1057 | | - memcpy(&pcie->pio, &res, sizeof(res)); |
---|
1058 | | - pcie->pio.name = node->full_name; |
---|
1059 | | - |
---|
1060 | | - pcie->io.start = range.cpu_addr; |
---|
1061 | | - pcie->io.end = range.cpu_addr + range.size - 1; |
---|
1062 | | - pcie->io.flags = IORESOURCE_MEM; |
---|
1063 | | - pcie->io.name = "I/O"; |
---|
1064 | | - |
---|
1065 | | - memcpy(&res, &pcie->io, sizeof(res)); |
---|
1066 | | - break; |
---|
1067 | | - |
---|
1068 | | - case IORESOURCE_MEM: |
---|
1069 | | - pcie->offset.mem = res.start - range.pci_addr; |
---|
1070 | | - |
---|
1071 | | - memcpy(&pcie->mem, &res, sizeof(res)); |
---|
1072 | | - pcie->mem.name = "non-prefetchable"; |
---|
1073 | | - break; |
---|
1074 | | - } |
---|
1075 | | - } |
---|
1076 | | - |
---|
1077 | | - err = of_pci_parse_bus_range(node, &pcie->busn); |
---|
1078 | | - if (err < 0) { |
---|
1079 | | - dev_err(dev, "failed to parse bus ranges property: %d\n", err); |
---|
1080 | | - pcie->busn.name = node->name; |
---|
1081 | | - pcie->busn.start = 0; |
---|
1082 | | - pcie->busn.end = 0xff; |
---|
1083 | | - pcie->busn.flags = IORESOURCE_BUS; |
---|
1084 | | - } |
---|
1085 | 1031 | |
---|
1086 | 1032 | for_each_available_child_of_node(node, child) { |
---|
1087 | 1033 | int slot; |
---|
.. | .. |
---|
1117 | 1063 | return err; |
---|
1118 | 1064 | } |
---|
1119 | 1065 | |
---|
1120 | | -static int mtk_pcie_request_resources(struct mtk_pcie *pcie) |
---|
1121 | | -{ |
---|
1122 | | - struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); |
---|
1123 | | - struct list_head *windows = &host->windows; |
---|
1124 | | - struct device *dev = pcie->dev; |
---|
1125 | | - int err; |
---|
1126 | | - |
---|
1127 | | - pci_add_resource_offset(windows, &pcie->pio, pcie->offset.io); |
---|
1128 | | - pci_add_resource_offset(windows, &pcie->mem, pcie->offset.mem); |
---|
1129 | | - pci_add_resource(windows, &pcie->busn); |
---|
1130 | | - |
---|
1131 | | - err = devm_request_pci_bus_resources(dev, windows); |
---|
1132 | | - if (err < 0) |
---|
1133 | | - return err; |
---|
1134 | | - |
---|
1135 | | - err = devm_pci_remap_iospace(dev, &pcie->pio, pcie->io.start); |
---|
1136 | | - if (err) |
---|
1137 | | - return err; |
---|
1138 | | - |
---|
1139 | | - return 0; |
---|
1140 | | -} |
---|
1141 | | - |
---|
1142 | | -static int mtk_pcie_register_host(struct pci_host_bridge *host) |
---|
1143 | | -{ |
---|
1144 | | - struct mtk_pcie *pcie = pci_host_bridge_priv(host); |
---|
1145 | | - struct pci_bus *child; |
---|
1146 | | - int err; |
---|
1147 | | - |
---|
1148 | | - host->busnr = pcie->busn.start; |
---|
1149 | | - host->dev.parent = pcie->dev; |
---|
1150 | | - host->ops = pcie->soc->ops; |
---|
1151 | | - host->map_irq = of_irq_parse_and_map_pci; |
---|
1152 | | - host->swizzle_irq = pci_common_swizzle; |
---|
1153 | | - host->sysdata = pcie; |
---|
1154 | | - |
---|
1155 | | - err = pci_scan_root_bus_bridge(host); |
---|
1156 | | - if (err < 0) |
---|
1157 | | - return err; |
---|
1158 | | - |
---|
1159 | | - pci_bus_size_bridges(host->bus); |
---|
1160 | | - pci_bus_assign_resources(host->bus); |
---|
1161 | | - |
---|
1162 | | - list_for_each_entry(child, &host->bus->children, node) |
---|
1163 | | - pcie_bus_configure_settings(child); |
---|
1164 | | - |
---|
1165 | | - pci_bus_add_devices(host->bus); |
---|
1166 | | - |
---|
1167 | | - return 0; |
---|
1168 | | -} |
---|
1169 | | - |
---|
1170 | 1066 | static int mtk_pcie_probe(struct platform_device *pdev) |
---|
1171 | 1067 | { |
---|
1172 | 1068 | struct device *dev = &pdev->dev; |
---|
.. | .. |
---|
1189 | 1085 | if (err) |
---|
1190 | 1086 | return err; |
---|
1191 | 1087 | |
---|
1192 | | - err = mtk_pcie_request_resources(pcie); |
---|
1193 | | - if (err) |
---|
1194 | | - goto put_resources; |
---|
| 1088 | + host->ops = pcie->soc->ops; |
---|
| 1089 | + host->sysdata = pcie; |
---|
1195 | 1090 | |
---|
1196 | | - err = mtk_pcie_register_host(host); |
---|
| 1091 | + err = pci_host_probe(host); |
---|
1197 | 1092 | if (err) |
---|
1198 | 1093 | goto put_resources; |
---|
1199 | 1094 | |
---|
.. | .. |
---|
1205 | 1100 | |
---|
1206 | 1101 | return err; |
---|
1207 | 1102 | } |
---|
| 1103 | + |
---|
| 1104 | + |
---|
| 1105 | +static void mtk_pcie_free_resources(struct mtk_pcie *pcie) |
---|
| 1106 | +{ |
---|
| 1107 | + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); |
---|
| 1108 | + struct list_head *windows = &host->windows; |
---|
| 1109 | + |
---|
| 1110 | + pci_free_resource_list(windows); |
---|
| 1111 | +} |
---|
| 1112 | + |
---|
| 1113 | +static int mtk_pcie_remove(struct platform_device *pdev) |
---|
| 1114 | +{ |
---|
| 1115 | + struct mtk_pcie *pcie = platform_get_drvdata(pdev); |
---|
| 1116 | + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); |
---|
| 1117 | + |
---|
| 1118 | + pci_stop_root_bus(host->bus); |
---|
| 1119 | + pci_remove_root_bus(host->bus); |
---|
| 1120 | + mtk_pcie_free_resources(pcie); |
---|
| 1121 | + |
---|
| 1122 | + mtk_pcie_irq_teardown(pcie); |
---|
| 1123 | + |
---|
| 1124 | + mtk_pcie_put_resources(pcie); |
---|
| 1125 | + |
---|
| 1126 | + return 0; |
---|
| 1127 | +} |
---|
| 1128 | + |
---|
| 1129 | +static int __maybe_unused mtk_pcie_suspend_noirq(struct device *dev) |
---|
| 1130 | +{ |
---|
| 1131 | + struct mtk_pcie *pcie = dev_get_drvdata(dev); |
---|
| 1132 | + struct mtk_pcie_port *port; |
---|
| 1133 | + |
---|
| 1134 | + if (list_empty(&pcie->ports)) |
---|
| 1135 | + return 0; |
---|
| 1136 | + |
---|
| 1137 | + list_for_each_entry(port, &pcie->ports, list) { |
---|
| 1138 | + clk_disable_unprepare(port->pipe_ck); |
---|
| 1139 | + clk_disable_unprepare(port->obff_ck); |
---|
| 1140 | + clk_disable_unprepare(port->axi_ck); |
---|
| 1141 | + clk_disable_unprepare(port->aux_ck); |
---|
| 1142 | + clk_disable_unprepare(port->ahb_ck); |
---|
| 1143 | + clk_disable_unprepare(port->sys_ck); |
---|
| 1144 | + phy_power_off(port->phy); |
---|
| 1145 | + phy_exit(port->phy); |
---|
| 1146 | + } |
---|
| 1147 | + |
---|
| 1148 | + clk_disable_unprepare(pcie->free_ck); |
---|
| 1149 | + |
---|
| 1150 | + return 0; |
---|
| 1151 | +} |
---|
| 1152 | + |
---|
| 1153 | +static int __maybe_unused mtk_pcie_resume_noirq(struct device *dev) |
---|
| 1154 | +{ |
---|
| 1155 | + struct mtk_pcie *pcie = dev_get_drvdata(dev); |
---|
| 1156 | + struct mtk_pcie_port *port, *tmp; |
---|
| 1157 | + |
---|
| 1158 | + if (list_empty(&pcie->ports)) |
---|
| 1159 | + return 0; |
---|
| 1160 | + |
---|
| 1161 | + clk_prepare_enable(pcie->free_ck); |
---|
| 1162 | + |
---|
| 1163 | + list_for_each_entry_safe(port, tmp, &pcie->ports, list) |
---|
| 1164 | + mtk_pcie_enable_port(port); |
---|
| 1165 | + |
---|
| 1166 | + /* In case of EP was removed while system suspend. */ |
---|
| 1167 | + if (list_empty(&pcie->ports)) |
---|
| 1168 | + clk_disable_unprepare(pcie->free_ck); |
---|
| 1169 | + |
---|
| 1170 | + return 0; |
---|
| 1171 | +} |
---|
| 1172 | + |
---|
| 1173 | +static const struct dev_pm_ops mtk_pcie_pm_ops = { |
---|
| 1174 | + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_pcie_suspend_noirq, |
---|
| 1175 | + mtk_pcie_resume_noirq) |
---|
| 1176 | +}; |
---|
1208 | 1177 | |
---|
1209 | 1178 | static const struct mtk_pcie_soc mtk_pcie_soc_v1 = { |
---|
1210 | 1179 | .ops = &mtk_pcie_ops, |
---|
.. | .. |
---|
1244 | 1213 | |
---|
1245 | 1214 | static struct platform_driver mtk_pcie_driver = { |
---|
1246 | 1215 | .probe = mtk_pcie_probe, |
---|
| 1216 | + .remove = mtk_pcie_remove, |
---|
1247 | 1217 | .driver = { |
---|
1248 | 1218 | .name = "mtk-pcie", |
---|
1249 | 1219 | .of_match_table = mtk_pcie_ids, |
---|
1250 | 1220 | .suppress_bind_attrs = true, |
---|
| 1221 | + .pm = &mtk_pcie_pm_ops, |
---|
1251 | 1222 | }, |
---|
1252 | 1223 | }; |
---|
1253 | | -builtin_platform_driver(mtk_pcie_driver); |
---|
| 1224 | +module_platform_driver(mtk_pcie_driver); |
---|
| 1225 | +MODULE_LICENSE("GPL v2"); |
---|