ipq806x: fix wireless regression
[openwrt/openwrt.git] / target / linux / ipq806x / patches-4.9 / 0071-8-pcie-qcom-Fixed-pcie_phy_clk-branch-issue.patch
1 From b74bab6186131eea09459eedf5d737645a3559c9 Mon Sep 17 00:00:00 2001
2 From: Abhishek Sahu <absahu@codeaurora.org>
3 Date: Thu, 22 Dec 2016 11:18:45 +0530
4 Subject: pcie: qcom: Fixed pcie_phy_clk branch issue
5
6 Following backtraces are observed in PCIe deinit operation.
7
8 Hardware name: Qualcomm (Flattened Device Tree)
9 (unwind_backtrace) from [] (show_stack+0x10/0x14)
10 (show_stack) from [] (dump_stack+0x84/0x98)
11 (dump_stack) from [] (warn_slowpath_common+0x9c/0xb8)
12 (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40)
13 (warn_slowpath_fmt) from [] (clk_branch_wait+0x114/0x120)
14 (clk_branch_wait) from [] (clk_core_disable+0xd0/0x1f4)
15 (clk_core_disable) from [] (clk_disable+0x24/0x30)
16 (clk_disable) from [] (qcom_pcie_deinit_v0+0x6c/0xb8)
17 (qcom_pcie_deinit_v0) from [] (qcom_pcie_host_init+0xe0/0xe8)
18 (qcom_pcie_host_init) from [] (dw_pcie_host_init+0x3b0/0x538)
19 (dw_pcie_host_init) from [] (qcom_pcie_probe+0x20c/0x2e4)
20
21 pcie_phy_clk is generated for PCIe controller itself and the
22 GCC controls its branch operation. This error is coming since
23 the assert operations turn off the parent clock before branch
24 clock. Now this patch moves clk_disable_unprepare before assert
25 operations.
26
27 Similarly, during probe function, the clock branch operation
28 should be done after dessert operation. Currently, it does not
29 generate any error since bootloader enables the pcie_phy_clk
30 but the same error is coming during probe, if bootloader
31 disables pcie_phy_clk.
32
33 Change-Id: Ib29c154d10eb64363d9cc982ce5fd8107af5627d
34 Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
35 ---
36 drivers/pci/host/pcie-qcom.c | 16 +++++++---------
37 1 file changed, 7 insertions(+), 9 deletions(-)
38
39 --- a/drivers/pci/host/pcie-qcom.c
40 +++ b/drivers/pci/host/pcie-qcom.c
41 @@ -352,6 +352,7 @@ static void qcom_pcie_deinit_v0(struct q
42 {
43 struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
44
45 + clk_disable_unprepare(res->phy_clk);
46 reset_control_assert(res->pci_reset);
47 reset_control_assert(res->axi_reset);
48 reset_control_assert(res->ahb_reset);
49 @@ -360,7 +361,6 @@ static void qcom_pcie_deinit_v0(struct q
50 reset_control_assert(res->ext_reset);
51 clk_disable_unprepare(res->iface_clk);
52 clk_disable_unprepare(res->core_clk);
53 - clk_disable_unprepare(res->phy_clk);
54 clk_disable_unprepare(res->aux_clk);
55 clk_disable_unprepare(res->ref_clk);
56 regulator_disable(res->vdda);
57 @@ -416,12 +416,6 @@ static int qcom_pcie_init_v0(struct qcom
58 goto err_clk_core;
59 }
60
61 - ret = clk_prepare_enable(res->phy_clk);
62 - if (ret) {
63 - dev_err(dev, "cannot prepare/enable phy clock\n");
64 - goto err_clk_phy;
65 - }
66 -
67 ret = clk_prepare_enable(res->aux_clk);
68 if (ret) {
69 dev_err(dev, "cannot prepare/enable aux clock\n");
70 @@ -486,6 +480,12 @@ static int qcom_pcie_init_v0(struct qcom
71 return ret;
72 }
73
74 + ret = clk_prepare_enable(res->phy_clk);
75 + if (ret) {
76 + dev_err(dev, "cannot prepare/enable phy clock\n");
77 + goto err_deassert_ahb;
78 + }
79 +
80 /* wait for clock acquisition */
81 usleep_range(1000, 1500);
82 if (pcie->force_gen1) {
83 @@ -504,8 +504,6 @@ err_deassert_ahb:
84 err_clk_ref:
85 clk_disable_unprepare(res->aux_clk);
86 err_clk_aux:
87 - clk_disable_unprepare(res->phy_clk);
88 -err_clk_phy:
89 clk_disable_unprepare(res->core_clk);
90 err_clk_core:
91 clk_disable_unprepare(res->iface_clk);