7fdede52f49661990fa7665d8a938ba135ce2a6f
[openwrt/staging/xback.git] /
1 From 9f4f3dfad8cf08208fbb78b1b9cbf957c12618b9 Mon Sep 17 00:00:00 2001
2 From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
3 Date: Tue, 10 Oct 2023 21:29:14 +0530
4 Subject: [PATCH] PCI: qcom: Enable ASPM for platforms supporting 1.9.0 ops
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 ASPM is supported by Qcom host controllers/bridges on most of the recent
10 platforms and so the devices tested so far. But for enabling ASPM by
11 default (without using Kconfig, kernel command-line or sysfs), BIOS has
12 to enable ASPM on both host bridge and downstream devices during boot.
13
14 Unfortunately, none of the BIOS available on Qcom platforms enables
15 ASPM. Due to this, the platforms making use of Qcom SoCs draw high power
16 during runtime.
17
18 To fix this power draw issue, users have to enable ASPM using Kconfig,
19 kernel command-line, sysfs or the BIOS has to start enabling ASPM.
20
21 The latter may happen in the future, but that won't address the issue on
22 current platforms. Also, asking users to enable a feature to get the power
23 management right would provide an unpleasant out-of-the-box experience.
24
25 So the apt solution is to enable ASPM in the controller driver itself. And
26 this is being accomplished by calling pci_enable_link_state() in the newly
27 introduced host_post_init() callback for all the devices connected to the
28 bus. This function enables all supported link low power states for both
29 host bridge and the downstream devices.
30
31 Due to limited testing, ASPM is only enabled for platforms making use of
32 ops_1_9_0 callbacks.
33
34 [kwilczynski: commit log]
35 Link: https://lore.kernel.org/linux-pci/20231010155914.9516-3-manivannan.sadhasivam@linaro.org
36 Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
37 Signed-off-by: Krzysztof WilczyƄski <kwilczynski@kernel.org>
38 ---
39 drivers/pci/controller/dwc/pcie-qcom.c | 28 ++++++++++++++++++++++++++
40 1 file changed, 28 insertions(+)
41
42 --- a/drivers/pci/controller/dwc/pcie-qcom.c
43 +++ b/drivers/pci/controller/dwc/pcie-qcom.c
44 @@ -222,6 +222,7 @@ struct qcom_pcie_ops {
45 int (*get_resources)(struct qcom_pcie *pcie);
46 int (*init)(struct qcom_pcie *pcie);
47 int (*post_init)(struct qcom_pcie *pcie);
48 + void (*host_post_init)(struct qcom_pcie *pcie);
49 void (*deinit)(struct qcom_pcie *pcie);
50 void (*ltssm_enable)(struct qcom_pcie *pcie);
51 int (*config_sid)(struct qcom_pcie *pcie);
52 @@ -966,6 +967,22 @@ static int qcom_pcie_post_init_2_7_0(str
53 return 0;
54 }
55
56 +static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata)
57 +{
58 + /* Downstream devices need to be in D0 state before enabling PCI PM substates */
59 + pci_set_power_state(pdev, PCI_D0);
60 + pci_enable_link_state(pdev, PCIE_LINK_STATE_ALL);
61 +
62 + return 0;
63 +}
64 +
65 +static void qcom_pcie_host_post_init_2_7_0(struct qcom_pcie *pcie)
66 +{
67 + struct dw_pcie_rp *pp = &pcie->pci->pp;
68 +
69 + pci_walk_bus(pp->bridge->bus, qcom_pcie_enable_aspm, NULL);
70 +}
71 +
72 static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
73 {
74 struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
75 @@ -1224,9 +1241,19 @@ static void qcom_pcie_host_deinit(struct
76 pcie->cfg->ops->deinit(pcie);
77 }
78
79 +static void qcom_pcie_host_post_init(struct dw_pcie_rp *pp)
80 +{
81 + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
82 + struct qcom_pcie *pcie = to_qcom_pcie(pci);
83 +
84 + if (pcie->cfg->ops->host_post_init)
85 + pcie->cfg->ops->host_post_init(pcie);
86 +}
87 +
88 static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {
89 .host_init = qcom_pcie_host_init,
90 .host_deinit = qcom_pcie_host_deinit,
91 + .host_post_init = qcom_pcie_host_post_init,
92 };
93
94 /* Qcom IP rev.: 2.1.0 Synopsys IP rev.: 4.01a */
95 @@ -1288,6 +1315,7 @@ static const struct qcom_pcie_ops ops_1_
96 .get_resources = qcom_pcie_get_resources_2_7_0,
97 .init = qcom_pcie_init_2_7_0,
98 .post_init = qcom_pcie_post_init_2_7_0,
99 + .host_post_init = qcom_pcie_host_post_init_2_7_0,
100 .deinit = qcom_pcie_deinit_2_7_0,
101 .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
102 .config_sid = qcom_pcie_config_sid_1_9_0,