4d2da5f7682d1f803f97ab1760ba533e0aa845fa
[openwrt/staging/jogo.git] /
1 From 6a114526af4689938863bf34976c83bfd279f517 Mon Sep 17 00:00:00 2001
2 From: Ansuel Smith <ansuelsmth@gmail.com>
3 Date: Mon, 15 Jun 2020 23:06:02 +0200
4 Subject: PCI: qcom: Use bulk clk api and assert on error
5
6 Rework 2.1.0 revision to use bulk clk api and fix missing assert on
7 reset_control_deassert error.
8
9 Link: https://lore.kernel.org/r/20200615210608.21469-7-ansuelsmth@gmail.com
10 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
11 Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
12 Reviewed-by: Rob Herring <robh@kernel.org>
13 Acked-by: Stanimir Varbanov <svarbanov@mm-sol.com>
14 ---
15 drivers/pci/controller/dwc/pcie-qcom.c | 131 ++++++++++++---------------------
16 1 file changed, 46 insertions(+), 85 deletions(-)
17
18 --- a/drivers/pci/controller/dwc/pcie-qcom.c
19 +++ b/drivers/pci/controller/dwc/pcie-qcom.c
20 @@ -81,12 +81,9 @@
21 #define SLV_ADDR_SPACE_SZ 0x10000000
22
23 #define QCOM_PCIE_2_1_0_MAX_SUPPLY 3
24 +#define QCOM_PCIE_2_1_0_MAX_CLOCKS 5
25 struct qcom_pcie_resources_2_1_0 {
26 - struct clk *iface_clk;
27 - struct clk *core_clk;
28 - struct clk *phy_clk;
29 - struct clk *aux_clk;
30 - struct clk *ref_clk;
31 + struct clk_bulk_data clks[QCOM_PCIE_2_1_0_MAX_CLOCKS];
32 struct reset_control *pci_reset;
33 struct reset_control *axi_reset;
34 struct reset_control *ahb_reset;
35 @@ -226,25 +223,21 @@ static int qcom_pcie_get_resources_2_1_0
36 if (ret)
37 return ret;
38
39 - res->iface_clk = devm_clk_get(dev, "iface");
40 - if (IS_ERR(res->iface_clk))
41 - return PTR_ERR(res->iface_clk);
42 -
43 - res->core_clk = devm_clk_get(dev, "core");
44 - if (IS_ERR(res->core_clk))
45 - return PTR_ERR(res->core_clk);
46 -
47 - res->phy_clk = devm_clk_get(dev, "phy");
48 - if (IS_ERR(res->phy_clk))
49 - return PTR_ERR(res->phy_clk);
50 -
51 - res->aux_clk = devm_clk_get_optional(dev, "aux");
52 - if (IS_ERR(res->aux_clk))
53 - return PTR_ERR(res->aux_clk);
54 -
55 - res->ref_clk = devm_clk_get_optional(dev, "ref");
56 - if (IS_ERR(res->ref_clk))
57 - return PTR_ERR(res->ref_clk);
58 + res->clks[0].id = "iface";
59 + res->clks[1].id = "core";
60 + res->clks[2].id = "phy";
61 + res->clks[3].id = "aux";
62 + res->clks[4].id = "ref";
63 +
64 + /* iface, core, phy are required */
65 + ret = devm_clk_bulk_get(dev, 3, res->clks);
66 + if (ret < 0)
67 + return ret;
68 +
69 + /* aux, ref are optional */
70 + ret = devm_clk_bulk_get_optional(dev, 2, res->clks + 3);
71 + if (ret < 0)
72 + return ret;
73
74 res->pci_reset = devm_reset_control_get_exclusive(dev, "pci");
75 if (IS_ERR(res->pci_reset))
76 @@ -274,17 +267,13 @@ static void qcom_pcie_deinit_2_1_0(struc
77 {
78 struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
79
80 - clk_disable_unprepare(res->phy_clk);
81 + clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks);
82 reset_control_assert(res->pci_reset);
83 reset_control_assert(res->axi_reset);
84 reset_control_assert(res->ahb_reset);
85 reset_control_assert(res->por_reset);
86 reset_control_assert(res->ext_reset);
87 reset_control_assert(res->phy_reset);
88 - clk_disable_unprepare(res->iface_clk);
89 - clk_disable_unprepare(res->core_clk);
90 - clk_disable_unprepare(res->aux_clk);
91 - clk_disable_unprepare(res->ref_clk);
92 regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
93 }
94
95 @@ -302,36 +291,6 @@ static int qcom_pcie_init_2_1_0(struct q
96 return ret;
97 }
98
99 - ret = reset_control_assert(res->ahb_reset);
100 - if (ret) {
101 - dev_err(dev, "cannot assert ahb reset\n");
102 - goto err_assert_ahb;
103 - }
104 -
105 - ret = clk_prepare_enable(res->iface_clk);
106 - if (ret) {
107 - dev_err(dev, "cannot prepare/enable iface clock\n");
108 - goto err_assert_ahb;
109 - }
110 -
111 - ret = clk_prepare_enable(res->core_clk);
112 - if (ret) {
113 - dev_err(dev, "cannot prepare/enable core clock\n");
114 - goto err_clk_core;
115 - }
116 -
117 - ret = clk_prepare_enable(res->aux_clk);
118 - if (ret) {
119 - dev_err(dev, "cannot prepare/enable aux clock\n");
120 - goto err_clk_aux;
121 - }
122 -
123 - ret = clk_prepare_enable(res->ref_clk);
124 - if (ret) {
125 - dev_err(dev, "cannot prepare/enable ref clock\n");
126 - goto err_clk_ref;
127 - }
128 -
129 ret = reset_control_deassert(res->ahb_reset);
130 if (ret) {
131 dev_err(dev, "cannot deassert ahb reset\n");
132 @@ -341,48 +300,46 @@ static int qcom_pcie_init_2_1_0(struct q
133 ret = reset_control_deassert(res->ext_reset);
134 if (ret) {
135 dev_err(dev, "cannot deassert ext reset\n");
136 - goto err_deassert_ahb;
137 + goto err_deassert_ext;
138 }
139
140 - /* enable PCIe clocks and resets */
141 - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
142 - val &= ~BIT(0);
143 - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
144 -
145 - /* enable external reference clock */
146 - val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK);
147 - val |= BIT(16);
148 - writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
149 -
150 ret = reset_control_deassert(res->phy_reset);
151 if (ret) {
152 dev_err(dev, "cannot deassert phy reset\n");
153 - return ret;
154 + goto err_deassert_phy;
155 }
156
157 ret = reset_control_deassert(res->pci_reset);
158 if (ret) {
159 dev_err(dev, "cannot deassert pci reset\n");
160 - return ret;
161 + goto err_deassert_pci;
162 }
163
164 ret = reset_control_deassert(res->por_reset);
165 if (ret) {
166 dev_err(dev, "cannot deassert por reset\n");
167 - return ret;
168 + goto err_deassert_por;
169 }
170
171 ret = reset_control_deassert(res->axi_reset);
172 if (ret) {
173 dev_err(dev, "cannot deassert axi reset\n");
174 - return ret;
175 + goto err_deassert_axi;
176 }
177
178 - ret = clk_prepare_enable(res->phy_clk);
179 - if (ret) {
180 - dev_err(dev, "cannot prepare/enable phy clock\n");
181 - goto err_deassert_ahb;
182 - }
183 + ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks);
184 + if (ret)
185 + goto err_clks;
186 +
187 + /* enable PCIe clocks and resets */
188 + val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
189 + val &= ~BIT(0);
190 + writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
191 +
192 + /* enable external reference clock */
193 + val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK);
194 + val |= BIT(16);
195 + writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
196
197 /* wait for clock acquisition */
198 usleep_range(1000, 1500);
199 @@ -396,15 +353,19 @@ static int qcom_pcie_init_2_1_0(struct q
200
201 return 0;
202
203 +err_clks:
204 + reset_control_assert(res->axi_reset);
205 +err_deassert_axi:
206 + reset_control_assert(res->por_reset);
207 +err_deassert_por:
208 + reset_control_assert(res->pci_reset);
209 +err_deassert_pci:
210 + reset_control_assert(res->phy_reset);
211 +err_deassert_phy:
212 + reset_control_assert(res->ext_reset);
213 +err_deassert_ext:
214 + reset_control_assert(res->ahb_reset);
215 err_deassert_ahb:
216 - clk_disable_unprepare(res->ref_clk);
217 -err_clk_ref:
218 - clk_disable_unprepare(res->aux_clk);
219 -err_clk_aux:
220 - clk_disable_unprepare(res->core_clk);
221 -err_clk_core:
222 - clk_disable_unprepare(res->iface_clk);
223 -err_assert_ahb:
224 regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
225
226 return ret;