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