brcm2708: Add support for raspberry pi 3 b+.
[openwrt/staging/wigyori.git] / target / linux / bcm53xx / patches-4.4 / 087-0002-PCI-iproc-Add-PAXC-interface-support.patch
1 From 943ebae781f519ecfecbfa1b997f15f59116e41d Mon Sep 17 00:00:00 2001
2 From: Ray Jui <rjui@broadcom.com>
3 Date: Fri, 4 Dec 2015 09:34:59 -0800
4 Subject: [PATCH 2/5] PCI: iproc: Add PAXC interface support
5
6 Traditionally, all iProc PCIe root complexes use PAXB-based wrapper, with
7 an integrated on-chip Serdes to support external endpoint devices. On
8 newer iProc platforms, a PAXC-based wrapper is introduced, for connection
9 with internally emulated PCIe endpoint devices in the ASIC.
10
11 Add support for PAXC-based iProc PCIe root complex in the iProc PCIe core
12 driver. This change factors out common logic between PAXB and PAXC, and
13 uses tables to store register offsets that are different between PAXB and
14 PAXC. This allows the driver to be scaled to support subsequent PAXC
15 revisions in the future.
16
17 Signed-off-by: Ray Jui <rjui@broadcom.com>
18 Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
19 Reviewed-by: Scott Branden <sbranden@broadcom.com>
20 ---
21 drivers/pci/host/pcie-iproc-platform.c | 24 +++-
22 drivers/pci/host/pcie-iproc.c | 202 +++++++++++++++++++++++++++------
23 drivers/pci/host/pcie-iproc.h | 19 ++++
24 3 files changed, 205 insertions(+), 40 deletions(-)
25
26 --- a/drivers/pci/host/pcie-iproc-platform.c
27 +++ b/drivers/pci/host/pcie-iproc-platform.c
28 @@ -26,8 +26,21 @@
29
30 #include "pcie-iproc.h"
31
32 +static const struct of_device_id iproc_pcie_of_match_table[] = {
33 + {
34 + .compatible = "brcm,iproc-pcie",
35 + .data = (int *)IPROC_PCIE_PAXB,
36 + }, {
37 + .compatible = "brcm,iproc-pcie-paxc",
38 + .data = (int *)IPROC_PCIE_PAXC,
39 + },
40 + { /* sentinel */ }
41 +};
42 +MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
43 +
44 static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
45 {
46 + const struct of_device_id *of_id;
47 struct iproc_pcie *pcie;
48 struct device_node *np = pdev->dev.of_node;
49 struct resource reg;
50 @@ -35,11 +48,16 @@ static int iproc_pcie_pltfm_probe(struct
51 LIST_HEAD(res);
52 int ret;
53
54 + of_id = of_match_device(iproc_pcie_of_match_table, &pdev->dev);
55 + if (!of_id)
56 + return -EINVAL;
57 +
58 pcie = devm_kzalloc(&pdev->dev, sizeof(struct iproc_pcie), GFP_KERNEL);
59 if (!pcie)
60 return -ENOMEM;
61
62 pcie->dev = &pdev->dev;
63 + pcie->type = (enum iproc_pcie_type)of_id->data;
64 platform_set_drvdata(pdev, pcie);
65
66 ret = of_address_to_resource(np, 0, &reg);
67 @@ -114,12 +132,6 @@ static int iproc_pcie_pltfm_remove(struc
68 return iproc_pcie_remove(pcie);
69 }
70
71 -static const struct of_device_id iproc_pcie_of_match_table[] = {
72 - { .compatible = "brcm,iproc-pcie", },
73 - { /* sentinel */ }
74 -};
75 -MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
76 -
77 static struct platform_driver iproc_pcie_pltfm_driver = {
78 .driver = {
79 .name = "iproc-pcie",
80 --- a/drivers/pci/host/pcie-iproc.c
81 +++ b/drivers/pci/host/pcie-iproc.c
82 @@ -30,20 +30,16 @@
83
84 #include "pcie-iproc.h"
85
86 -#define CLK_CONTROL_OFFSET 0x000
87 #define EP_PERST_SOURCE_SELECT_SHIFT 2
88 #define EP_PERST_SOURCE_SELECT BIT(EP_PERST_SOURCE_SELECT_SHIFT)
89 #define EP_MODE_SURVIVE_PERST_SHIFT 1
90 #define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT)
91 #define RC_PCIE_RST_OUTPUT_SHIFT 0
92 #define RC_PCIE_RST_OUTPUT BIT(RC_PCIE_RST_OUTPUT_SHIFT)
93 +#define PAXC_RESET_MASK 0x7f
94
95 -#define CFG_IND_ADDR_OFFSET 0x120
96 #define CFG_IND_ADDR_MASK 0x00001ffc
97
98 -#define CFG_IND_DATA_OFFSET 0x124
99 -
100 -#define CFG_ADDR_OFFSET 0x1f8
101 #define CFG_ADDR_BUS_NUM_SHIFT 20
102 #define CFG_ADDR_BUS_NUM_MASK 0x0ff00000
103 #define CFG_ADDR_DEV_NUM_SHIFT 15
104 @@ -55,12 +51,8 @@
105 #define CFG_ADDR_CFG_TYPE_SHIFT 0
106 #define CFG_ADDR_CFG_TYPE_MASK 0x00000003
107
108 -#define CFG_DATA_OFFSET 0x1fc
109 -
110 -#define SYS_RC_INTX_EN 0x330
111 #define SYS_RC_INTX_MASK 0xf
112
113 -#define PCIE_LINK_STATUS_OFFSET 0xf0c
114 #define PCIE_PHYLINKUP_SHIFT 3
115 #define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT)
116 #define PCIE_DL_ACTIVE_SHIFT 2
117 @@ -71,12 +63,54 @@
118 #define OARR_SIZE_CFG_SHIFT 1
119 #define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT)
120
121 -#define OARR_LO(window) (0xd20 + (window) * 8)
122 -#define OARR_HI(window) (0xd24 + (window) * 8)
123 -#define OMAP_LO(window) (0xd40 + (window) * 8)
124 -#define OMAP_HI(window) (0xd44 + (window) * 8)
125 -
126 #define MAX_NUM_OB_WINDOWS 2
127 +#define MAX_NUM_PAXC_PF 4
128 +
129 +#define IPROC_PCIE_REG_INVALID 0xffff
130 +
131 +enum iproc_pcie_reg {
132 + IPROC_PCIE_CLK_CTRL = 0,
133 + IPROC_PCIE_CFG_IND_ADDR,
134 + IPROC_PCIE_CFG_IND_DATA,
135 + IPROC_PCIE_CFG_ADDR,
136 + IPROC_PCIE_CFG_DATA,
137 + IPROC_PCIE_INTX_EN,
138 + IPROC_PCIE_OARR_LO,
139 + IPROC_PCIE_OARR_HI,
140 + IPROC_PCIE_OMAP_LO,
141 + IPROC_PCIE_OMAP_HI,
142 + IPROC_PCIE_LINK_STATUS,
143 +};
144 +
145 +/* iProc PCIe PAXB registers */
146 +static const u16 iproc_pcie_reg_paxb[] = {
147 + [IPROC_PCIE_CLK_CTRL] = 0x000,
148 + [IPROC_PCIE_CFG_IND_ADDR] = 0x120,
149 + [IPROC_PCIE_CFG_IND_DATA] = 0x124,
150 + [IPROC_PCIE_CFG_ADDR] = 0x1f8,
151 + [IPROC_PCIE_CFG_DATA] = 0x1fc,
152 + [IPROC_PCIE_INTX_EN] = 0x330,
153 + [IPROC_PCIE_OARR_LO] = 0xd20,
154 + [IPROC_PCIE_OARR_HI] = 0xd24,
155 + [IPROC_PCIE_OMAP_LO] = 0xd40,
156 + [IPROC_PCIE_OMAP_HI] = 0xd44,
157 + [IPROC_PCIE_LINK_STATUS] = 0xf0c,
158 +};
159 +
160 +/* iProc PCIe PAXC v1 registers */
161 +static const u16 iproc_pcie_reg_paxc[] = {
162 + [IPROC_PCIE_CLK_CTRL] = 0x000,
163 + [IPROC_PCIE_CFG_IND_ADDR] = 0x1f0,
164 + [IPROC_PCIE_CFG_IND_DATA] = 0x1f4,
165 + [IPROC_PCIE_CFG_ADDR] = 0x1f8,
166 + [IPROC_PCIE_CFG_DATA] = 0x1fc,
167 + [IPROC_PCIE_INTX_EN] = IPROC_PCIE_REG_INVALID,
168 + [IPROC_PCIE_OARR_LO] = IPROC_PCIE_REG_INVALID,
169 + [IPROC_PCIE_OARR_HI] = IPROC_PCIE_REG_INVALID,
170 + [IPROC_PCIE_OMAP_LO] = IPROC_PCIE_REG_INVALID,
171 + [IPROC_PCIE_OMAP_HI] = IPROC_PCIE_REG_INVALID,
172 + [IPROC_PCIE_LINK_STATUS] = IPROC_PCIE_REG_INVALID,
173 +};
174
175 static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
176 {
177 @@ -91,6 +125,65 @@ static inline struct iproc_pcie *iproc_d
178 return pcie;
179 }
180
181 +static inline bool iproc_pcie_reg_is_invalid(u16 reg_offset)
182 +{
183 + return !!(reg_offset == IPROC_PCIE_REG_INVALID);
184 +}
185 +
186 +static inline u16 iproc_pcie_reg_offset(struct iproc_pcie *pcie,
187 + enum iproc_pcie_reg reg)
188 +{
189 + return pcie->reg_offsets[reg];
190 +}
191 +
192 +static inline u32 iproc_pcie_read_reg(struct iproc_pcie *pcie,
193 + enum iproc_pcie_reg reg)
194 +{
195 + u16 offset = iproc_pcie_reg_offset(pcie, reg);
196 +
197 + if (iproc_pcie_reg_is_invalid(offset))
198 + return 0;
199 +
200 + return readl(pcie->base + offset);
201 +}
202 +
203 +static inline void iproc_pcie_write_reg(struct iproc_pcie *pcie,
204 + enum iproc_pcie_reg reg, u32 val)
205 +{
206 + u16 offset = iproc_pcie_reg_offset(pcie, reg);
207 +
208 + if (iproc_pcie_reg_is_invalid(offset))
209 + return;
210 +
211 + writel(val, pcie->base + offset);
212 +}
213 +
214 +static inline void iproc_pcie_ob_write(struct iproc_pcie *pcie,
215 + enum iproc_pcie_reg reg,
216 + unsigned window, u32 val)
217 +{
218 + u16 offset = iproc_pcie_reg_offset(pcie, reg);
219 +
220 + if (iproc_pcie_reg_is_invalid(offset))
221 + return;
222 +
223 + writel(val, pcie->base + offset + (window * 8));
224 +}
225 +
226 +static inline bool iproc_pcie_device_is_valid(struct iproc_pcie *pcie,
227 + unsigned int slot,
228 + unsigned int fn)
229 +{
230 + if (slot > 0)
231 + return false;
232 +
233 + /* PAXC can only support limited number of functions */
234 + if (pcie->type == IPROC_PCIE_PAXC && fn >= MAX_NUM_PAXC_PF)
235 + return false;
236 +
237 + return true;
238 +}
239 +
240 /**
241 * Note access to the configuration registers are protected at the higher layer
242 * by 'pci_lock' in drivers/pci/access.c
243 @@ -104,28 +197,34 @@ static void __iomem *iproc_pcie_map_cfg_
244 unsigned fn = PCI_FUNC(devfn);
245 unsigned busno = bus->number;
246 u32 val;
247 + u16 offset;
248 +
249 + if (!iproc_pcie_device_is_valid(pcie, slot, fn))
250 + return NULL;
251
252 /* root complex access */
253 if (busno == 0) {
254 - if (slot >= 1)
255 + iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_IND_ADDR,
256 + where & CFG_IND_ADDR_MASK);
257 + offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_IND_DATA);
258 + if (iproc_pcie_reg_is_invalid(offset))
259 return NULL;
260 - writel(where & CFG_IND_ADDR_MASK,
261 - pcie->base + CFG_IND_ADDR_OFFSET);
262 - return (pcie->base + CFG_IND_DATA_OFFSET);
263 + else
264 + return (pcie->base + offset);
265 }
266
267 - if (fn > 1)
268 - return NULL;
269 -
270 /* EP device access */
271 val = (busno << CFG_ADDR_BUS_NUM_SHIFT) |
272 (slot << CFG_ADDR_DEV_NUM_SHIFT) |
273 (fn << CFG_ADDR_FUNC_NUM_SHIFT) |
274 (where & CFG_ADDR_REG_NUM_MASK) |
275 (1 & CFG_ADDR_CFG_TYPE_MASK);
276 - writel(val, pcie->base + CFG_ADDR_OFFSET);
277 -
278 - return (pcie->base + CFG_DATA_OFFSET);
279 + iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_ADDR, val);
280 + offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_DATA);
281 + if (iproc_pcie_reg_is_invalid(offset))
282 + return NULL;
283 + else
284 + return (pcie->base + offset);
285 }
286
287 static struct pci_ops iproc_pcie_ops = {
288 @@ -138,18 +237,29 @@ static void iproc_pcie_reset(struct ipro
289 {
290 u32 val;
291
292 + if (pcie->type == IPROC_PCIE_PAXC) {
293 + val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
294 + val &= ~PAXC_RESET_MASK;
295 + iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
296 + udelay(100);
297 + val |= PAXC_RESET_MASK;
298 + iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
299 + udelay(100);
300 + return;
301 + }
302 +
303 /*
304 * Select perst_b signal as reset source. Put the device into reset,
305 * and then bring it out of reset
306 */
307 - val = readl(pcie->base + CLK_CONTROL_OFFSET);
308 + val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
309 val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST &
310 ~RC_PCIE_RST_OUTPUT;
311 - writel(val, pcie->base + CLK_CONTROL_OFFSET);
312 + iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
313 udelay(250);
314
315 val |= RC_PCIE_RST_OUTPUT;
316 - writel(val, pcie->base + CLK_CONTROL_OFFSET);
317 + iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
318 msleep(100);
319 }
320
321 @@ -160,7 +270,14 @@ static int iproc_pcie_check_link(struct
322 u16 pos, link_status;
323 bool link_is_active = false;
324
325 - val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET);
326 + /*
327 + * PAXC connects to emulated endpoint devices directly and does not
328 + * have a Serdes. Therefore skip the link detection logic here.
329 + */
330 + if (pcie->type == IPROC_PCIE_PAXC)
331 + return 0;
332 +
333 + val = iproc_pcie_read_reg(pcie, IPROC_PCIE_LINK_STATUS);
334 if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) {
335 dev_err(pcie->dev, "PHY or data link is INACTIVE!\n");
336 return -ENODEV;
337 @@ -221,7 +338,7 @@ static int iproc_pcie_check_link(struct
338
339 static void iproc_pcie_enable(struct iproc_pcie *pcie)
340 {
341 - writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN);
342 + iproc_pcie_write_reg(pcie, IPROC_PCIE_INTX_EN, SYS_RC_INTX_MASK);
343 }
344
345 /**
346 @@ -272,11 +389,15 @@ static int iproc_pcie_setup_ob(struct ip
347 axi_addr -= ob->axi_offset;
348
349 for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) {
350 - writel(lower_32_bits(axi_addr) | OARR_VALID |
351 - (ob->set_oarr_size ? 1 : 0), pcie->base + OARR_LO(i));
352 - writel(upper_32_bits(axi_addr), pcie->base + OARR_HI(i));
353 - writel(lower_32_bits(pci_addr), pcie->base + OMAP_LO(i));
354 - writel(upper_32_bits(pci_addr), pcie->base + OMAP_HI(i));
355 + iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_LO, i,
356 + lower_32_bits(axi_addr) | OARR_VALID |
357 + (ob->set_oarr_size ? 1 : 0));
358 + iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_HI, i,
359 + upper_32_bits(axi_addr));
360 + iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_LO, i,
361 + lower_32_bits(pci_addr));
362 + iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_HI, i,
363 + upper_32_bits(pci_addr));
364
365 size -= ob->window_size;
366 if (size == 0)
367 @@ -340,6 +461,19 @@ int iproc_pcie_setup(struct iproc_pcie *
368 goto err_exit_phy;
369 }
370
371 + switch (pcie->type) {
372 + case IPROC_PCIE_PAXB:
373 + pcie->reg_offsets = iproc_pcie_reg_paxb;
374 + break;
375 + case IPROC_PCIE_PAXC:
376 + pcie->reg_offsets = iproc_pcie_reg_paxc;
377 + break;
378 + default:
379 + dev_err(pcie->dev, "incompatible iProc PCIe interface\n");
380 + ret = -EINVAL;
381 + goto err_power_off_phy;
382 + }
383 +
384 iproc_pcie_reset(pcie);
385
386 if (pcie->need_ob_cfg) {
387 --- a/drivers/pci/host/pcie-iproc.h
388 +++ b/drivers/pci/host/pcie-iproc.h
389 @@ -15,6 +15,20 @@
390 #define _PCIE_IPROC_H
391
392 /**
393 + * iProc PCIe interface type
394 + *
395 + * PAXB is the wrapper used in root complex that can be connected to an
396 + * external endpoint device.
397 + *
398 + * PAXC is the wrapper used in root complex dedicated for internal emulated
399 + * endpoint devices.
400 + */
401 +enum iproc_pcie_type {
402 + IPROC_PCIE_PAXB = 0,
403 + IPROC_PCIE_PAXC,
404 +};
405 +
406 +/**
407 * iProc PCIe outbound mapping
408 * @set_oarr_size: indicates the OARR size bit needs to be set
409 * @axi_offset: offset from the AXI address to the internal address used by
410 @@ -29,7 +43,10 @@ struct iproc_pcie_ob {
411
412 /**
413 * iProc PCIe device
414 + *
415 * @dev: pointer to device data structure
416 + * @type: iProc PCIe interface type
417 + * @reg_offsets: register offsets
418 * @base: PCIe host controller I/O register base
419 * @sysdata: Per PCI controller data (ARM-specific)
420 * @root_bus: pointer to root bus
421 @@ -41,6 +58,8 @@ struct iproc_pcie_ob {
422 */
423 struct iproc_pcie {
424 struct device *dev;
425 + enum iproc_pcie_type type;
426 + const u16 *reg_offsets;
427 void __iomem *base;
428 #ifdef CONFIG_ARM
429 struct pci_sys_data sysdata;