aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc/pcie-designware.c
diff options
context:
space:
mode:
authorShawn Lin <shawn.lin@rock-chips.com>2018-05-30 21:12:37 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-06-08 08:50:11 -0400
commit6e0832fa432ec99c94caee733c8f5851cf85560b (patch)
treec4326f9e2d8ff1a6cb17e959fc5268c9e577ca94 /drivers/pci/controller/dwc/pcie-designware.c
parent3a3869f1c443383ef8354ffa0e5fb8df65d8b549 (diff)
PCI: Collect all native drivers under drivers/pci/controller/
Native PCI drivers for root complex devices were originally all in drivers/pci/host/. Some of these devices can also be operated in endpoint mode. Drivers for endpoint mode didn't seem to fit in the "host" directory, so we put both the root complex and endpoint drivers in per-device directories, e.g., drivers/pci/dwc/, drivers/pci/cadence/, etc. These per-device directories contain trivial Kconfig and Makefiles and clutter drivers/pci/. Make a new drivers/pci/controllers/ directory and collect all the device-specific drivers there. No functional change intended. Link: https://lkml.kernel.org/r/1520304202-232891-1-git-send-email-shawn.lin@rock-chips.com Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> [bhelgaas: changelog] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-designware.c')
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
new file mode 100644
index 000000000000..778c4f76a884
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -0,0 +1,394 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Synopsys DesignWare PCIe host controller driver
4 *
5 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
6 * http://www.samsung.com
7 *
8 * Author: Jingoo Han <jg1.han@samsung.com>
9 */
10
11#include <linux/delay.h>
12#include <linux/of.h>
13#include <linux/types.h>
14
15#include "pcie-designware.h"
16
17/* PCIe Port Logic registers */
18#define PLR_OFFSET 0x700
19#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c)
20#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4)
21#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29)
22
23int dw_pcie_read(void __iomem *addr, int size, u32 *val)
24{
25 if ((uintptr_t)addr & (size - 1)) {
26 *val = 0;
27 return PCIBIOS_BAD_REGISTER_NUMBER;
28 }
29
30 if (size == 4) {
31 *val = readl(addr);
32 } else if (size == 2) {
33 *val = readw(addr);
34 } else if (size == 1) {
35 *val = readb(addr);
36 } else {
37 *val = 0;
38 return PCIBIOS_BAD_REGISTER_NUMBER;
39 }
40
41 return PCIBIOS_SUCCESSFUL;
42}
43
44int dw_pcie_write(void __iomem *addr, int size, u32 val)
45{
46 if ((uintptr_t)addr & (size - 1))
47 return PCIBIOS_BAD_REGISTER_NUMBER;
48
49 if (size == 4)
50 writel(val, addr);
51 else if (size == 2)
52 writew(val, addr);
53 else if (size == 1)
54 writeb(val, addr);
55 else
56 return PCIBIOS_BAD_REGISTER_NUMBER;
57
58 return PCIBIOS_SUCCESSFUL;
59}
60
61u32 __dw_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
62 size_t size)
63{
64 int ret;
65 u32 val;
66
67 if (pci->ops->read_dbi)
68 return pci->ops->read_dbi(pci, base, reg, size);
69
70 ret = dw_pcie_read(base + reg, size, &val);
71 if (ret)
72 dev_err(pci->dev, "Read DBI address failed\n");
73
74 return val;
75}
76
77void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
78 size_t size, u32 val)
79{
80 int ret;
81
82 if (pci->ops->write_dbi) {
83 pci->ops->write_dbi(pci, base, reg, size, val);
84 return;
85 }
86
87 ret = dw_pcie_write(base + reg, size, val);
88 if (ret)
89 dev_err(pci->dev, "Write DBI address failed\n");
90}
91
92static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
93{
94 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
95
96 return dw_pcie_readl_dbi(pci, offset + reg);
97}
98
99static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
100 u32 val)
101{
102 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
103
104 dw_pcie_writel_dbi(pci, offset + reg, val);
105}
106
107static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
108 int type, u64 cpu_addr,
109 u64 pci_addr, u32 size)
110{
111 u32 retries, val;
112
113 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
114 lower_32_bits(cpu_addr));
115 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
116 upper_32_bits(cpu_addr));
117 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
118 lower_32_bits(cpu_addr + size - 1));
119 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
120 lower_32_bits(pci_addr));
121 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
122 upper_32_bits(pci_addr));
123 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
124 type);
125 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
126 PCIE_ATU_ENABLE);
127
128 /*
129 * Make sure ATU enable takes effect before any subsequent config
130 * and I/O accesses.
131 */
132 for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
133 val = dw_pcie_readl_ob_unroll(pci, index,
134 PCIE_ATU_UNR_REGION_CTRL2);
135 if (val & PCIE_ATU_ENABLE)
136 return;
137
138 usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
139 }
140 dev_err(pci->dev, "Outbound iATU is not being enabled\n");
141}
142
143void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
144 u64 cpu_addr, u64 pci_addr, u32 size)
145{
146 u32 retries, val;
147
148 if (pci->ops->cpu_addr_fixup)
149 cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
150
151 if (pci->iatu_unroll_enabled) {
152 dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr,
153 pci_addr, size);
154 return;
155 }
156
157 dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT,
158 PCIE_ATU_REGION_OUTBOUND | index);
159 dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE,
160 lower_32_bits(cpu_addr));
161 dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE,
162 upper_32_bits(cpu_addr));
163 dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT,
164 lower_32_bits(cpu_addr + size - 1));
165 dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET,
166 lower_32_bits(pci_addr));
167 dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
168 upper_32_bits(pci_addr));
169 dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
170 dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
171
172 /*
173 * Make sure ATU enable takes effect before any subsequent config
174 * and I/O accesses.
175 */
176 for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
177 val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
178 if (val & PCIE_ATU_ENABLE)
179 return;
180
181 usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
182 }
183 dev_err(pci->dev, "Outbound iATU is not being enabled\n");
184}
185
186static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
187{
188 u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
189
190 return dw_pcie_readl_dbi(pci, offset + reg);
191}
192
193static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
194 u32 val)
195{
196 u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
197
198 dw_pcie_writel_dbi(pci, offset + reg, val);
199}
200
201static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
202 int bar, u64 cpu_addr,
203 enum dw_pcie_as_type as_type)
204{
205 int type;
206 u32 retries, val;
207
208 dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
209 lower_32_bits(cpu_addr));
210 dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
211 upper_32_bits(cpu_addr));
212
213 switch (as_type) {
214 case DW_PCIE_AS_MEM:
215 type = PCIE_ATU_TYPE_MEM;
216 break;
217 case DW_PCIE_AS_IO:
218 type = PCIE_ATU_TYPE_IO;
219 break;
220 default:
221 return -EINVAL;
222 }
223
224 dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type);
225 dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
226 PCIE_ATU_ENABLE |
227 PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
228
229 /*
230 * Make sure ATU enable takes effect before any subsequent config
231 * and I/O accesses.
232 */
233 for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
234 val = dw_pcie_readl_ib_unroll(pci, index,
235 PCIE_ATU_UNR_REGION_CTRL2);
236 if (val & PCIE_ATU_ENABLE)
237 return 0;
238
239 usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
240 }
241 dev_err(pci->dev, "Inbound iATU is not being enabled\n");
242
243 return -EBUSY;
244}
245
246int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
247 u64 cpu_addr, enum dw_pcie_as_type as_type)
248{
249 int type;
250 u32 retries, val;
251
252 if (pci->iatu_unroll_enabled)
253 return dw_pcie_prog_inbound_atu_unroll(pci, index, bar,
254 cpu_addr, as_type);
255
256 dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_INBOUND |
257 index);
258 dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, lower_32_bits(cpu_addr));
259 dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, upper_32_bits(cpu_addr));
260
261 switch (as_type) {
262 case DW_PCIE_AS_MEM:
263 type = PCIE_ATU_TYPE_MEM;
264 break;
265 case DW_PCIE_AS_IO:
266 type = PCIE_ATU_TYPE_IO;
267 break;
268 default:
269 return -EINVAL;
270 }
271
272 dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
273 dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE
274 | PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
275
276 /*
277 * Make sure ATU enable takes effect before any subsequent config
278 * and I/O accesses.
279 */
280 for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
281 val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
282 if (val & PCIE_ATU_ENABLE)
283 return 0;
284
285 usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
286 }
287 dev_err(pci->dev, "Inbound iATU is not being enabled\n");
288
289 return -EBUSY;
290}
291
292void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
293 enum dw_pcie_region_type type)
294{
295 int region;
296
297 switch (type) {
298 case DW_PCIE_REGION_INBOUND:
299 region = PCIE_ATU_REGION_INBOUND;
300 break;
301 case DW_PCIE_REGION_OUTBOUND:
302 region = PCIE_ATU_REGION_OUTBOUND;
303 break;
304 default:
305 return;
306 }
307
308 dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index);
309 dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, ~PCIE_ATU_ENABLE);
310}
311
312int dw_pcie_wait_for_link(struct dw_pcie *pci)
313{
314 int retries;
315
316 /* Check if the link is up or not */
317 for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
318 if (dw_pcie_link_up(pci)) {
319 dev_info(pci->dev, "Link up\n");
320 return 0;
321 }
322 usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
323 }
324
325 dev_err(pci->dev, "Phy link never came up\n");
326
327 return -ETIMEDOUT;
328}
329
330int dw_pcie_link_up(struct dw_pcie *pci)
331{
332 u32 val;
333
334 if (pci->ops->link_up)
335 return pci->ops->link_up(pci);
336
337 val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1);
338 return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) &&
339 (!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING)));
340}
341
342void dw_pcie_setup(struct dw_pcie *pci)
343{
344 int ret;
345 u32 val;
346 u32 lanes;
347 struct device *dev = pci->dev;
348 struct device_node *np = dev->of_node;
349
350 ret = of_property_read_u32(np, "num-lanes", &lanes);
351 if (ret)
352 lanes = 0;
353
354 /* Set the number of lanes */
355 val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
356 val &= ~PORT_LINK_MODE_MASK;
357 switch (lanes) {
358 case 1:
359 val |= PORT_LINK_MODE_1_LANES;
360 break;
361 case 2:
362 val |= PORT_LINK_MODE_2_LANES;
363 break;
364 case 4:
365 val |= PORT_LINK_MODE_4_LANES;
366 break;
367 case 8:
368 val |= PORT_LINK_MODE_8_LANES;
369 break;
370 default:
371 dev_err(pci->dev, "num-lanes %u: invalid value\n", lanes);
372 return;
373 }
374 dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
375
376 /* Set link width speed control register */
377 val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
378 val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
379 switch (lanes) {
380 case 1:
381 val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
382 break;
383 case 2:
384 val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
385 break;
386 case 4:
387 val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
388 break;
389 case 8:
390 val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
391 break;
392 }
393 dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
394}