imx6: update PCIe driver
[openwrt.git] / target / linux / imx6 / patches-3.10 / 0012-PCI-imx6-Add-support-for-i.MX6-PCIe-controller.patch
1 Subject: [v6,3/3] PCI: imx6: Add support for i.MX6 PCIe controller
2 From: Sean Cross <xobs@kosagi.com>
3
4 Add support for the PCIe port present on the i.MX6 family of controllers.
5 These use the Synopsis Designware core tied to their own PHY.
6
7 Signed-off-by: Sean Cross <xobs@kosagi.com>
8 Acked-by: Bjorn Helgaas <bhelgaas@google.com>
9 Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
10 ---
11  arch/arm/boot/dts/imx6qdl.dtsi                     |   16 +
12  arch/arm/mach-imx/Kconfig                          |    2 +
13  arch/arm/mach-imx/clk-imx6q.c                      |    4 +
14  drivers/pci/host/Kconfig                           |    6 +
15  drivers/pci/host/Makefile                          |    1 +
16  drivers/pci/host/pci-imx6.c                        |  576 ++++++++++++++++++++
17  7 files changed, 611 insertions(+), 1 deletion(-)
18  create mode 100644 drivers/pci/host/pci-imx6.c
19
20 diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
21 index ccd55c2..125202e 100644
22 --- a/arch/arm/boot/dts/imx6qdl.dtsi
23 +++ b/arch/arm/boot/dts/imx6qdl.dtsi
24 @@ -116,6 +116,22 @@
25                         arm,data-latency = <4 2 3>;
26                 };
27  
28 +               pcie: pcie@0x01000000 {
29 +                       compatible = "fsl,imx6q-pcie", "snps,dw-pcie";
30 +                       reg = <0x01ffc000 0x4000>; /* DBI */
31 +                       #address-cells = <3>;
32 +                       #size-cells = <2>;
33 +                       device_type = "pci";
34 +                       ranges = <0x00000800 0 0x01f00000 0x01f00000 0 0x00080000 /* configuration space */
35 +                                 0x81000000 0 0          0x01f80000 0 0x00010000 /* downstream I/O */
36 +                                 0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
37 +                       num-lanes = <1>;
38 +                       interrupts = <0 123 0x04>;
39 +                       clocks = <&clks 189>, <&clks 187>, <&clks 205>, <&clks 144>;
40 +                       clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
41 +                       status = "disabled";
42 +               };
43 +
44                 pmu {
45                         compatible = "arm,cortex-a9-pmu";
46                         interrupts = <0 94 0x04>;
47 diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
48 index 29a8af6..e6ac281 100644
49 --- a/arch/arm/mach-imx/Kconfig
50 +++ b/arch/arm/mach-imx/Kconfig
51 @@ -801,6 +801,8 @@ config SOC_IMX6Q
52         select HAVE_IMX_SRC
53         select HAVE_SMP
54         select MFD_SYSCON
55 +       select MIGHT_HAVE_PCI
56 +       select PCI_DOMAINS if PCI
57         select PINCTRL
58         select PINCTRL_IMX6Q
59         select PL310_ERRATA_588369 if CACHE_PL310
60 diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
61 index d94be84..6956995 100644
62 --- a/arch/arm/mach-imx/clk-imx6q.c
63 +++ b/arch/arm/mach-imx/clk-imx6q.c
64 @@ -621,6 +621,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
65         if (ret)
66                 pr_warn("failed to set up CLKO: %d\n", ret);
67  
68 +       /* All existing boards with PCIe use LVDS1 */
69 +       if (IS_ENABLED(CONFIG_PCI_IMX6))
70 +               clk_set_parent(clk[lvds1_sel], clk[sata_ref]);
71 +
72         /* Set initial power mode */
73         imx6q_set_lpm(WAIT_CLOCKED);
74  
75 --- /dev/null
76 +++ b/drivers/pci/host/Kconfig
77 @@ -0,0 +1,13 @@
78 +menu "PCI host controller drivers"
79 +       depends on PCI
80 +
81 +config PCIE_DW
82 +       bool
83 +
84 +config PCI_IMX6
85 +       bool "Freescale i.MX6 PCIe controller"
86 +       depends on SOC_IMX6Q
87 +       select PCIEPORTBUS
88 +       select PCIE_DW
89 +
90 +endmenu
91 --- /dev/null
92 +++ b/drivers/pci/host/Makefile
93 @@ -0,0 +1,2 @@
94 +obj-$(CONFIG_PCIE_DW) += pcie-designware.o
95 +obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
96 --- /dev/null
97 +++ b/drivers/pci/host/pci-imx6.c
98 @@ -0,0 +1,576 @@
99 +/*
100 + * PCIe host controller driver for Freescale i.MX6 SoCs
101 + *
102 + * Copyright (C) 2013 Kosagi
103 + *             http://www.kosagi.com
104 + *
105 + * Author: Sean Cross <xobs@kosagi.com>
106 + *
107 + * This program is free software; you can redistribute it and/or modify
108 + * it under the terms of the GNU General Public License version 2 as
109 + * published by the Free Software Foundation.
110 + */
111 +
112 +#include <linux/clk.h>
113 +#include <linux/delay.h>
114 +#include <linux/gpio.h>
115 +#include <linux/kernel.h>
116 +#include <linux/mfd/syscon.h>
117 +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
118 +#include <linux/module.h>
119 +#include <linux/of_gpio.h>
120 +#include <linux/pci.h>
121 +#include <linux/platform_device.h>
122 +#include <linux/regmap.h>
123 +#include <linux/resource.h>
124 +#include <linux/signal.h>
125 +#include <linux/types.h>
126 +
127 +#include "pcie-designware.h"
128 +
129 +#define to_imx6_pcie(x)        container_of(x, struct imx6_pcie, pp)
130 +
131 +struct imx6_pcie {
132 +       int                     reset_gpio;
133 +       int                     power_on_gpio;
134 +       int                     wake_up_gpio;
135 +       int                     disable_gpio;
136 +       struct clk              *lvds_gate;
137 +       struct clk              *sata_ref_100m;
138 +       struct clk              *pcie_ref_125m;
139 +       struct clk              *pcie_axi;
140 +       struct pcie_port        pp;
141 +       struct regmap           *iomuxc_gpr;
142 +       void __iomem            *mem_base;
143 +};
144 +
145 +/* PCIe Port Logic registers (memory-mapped) */
146 +#define PL_OFFSET 0x700
147 +#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
148 +#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
149 +
150 +#define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
151 +#define PCIE_PHY_CTRL_DATA_LOC 0
152 +#define PCIE_PHY_CTRL_CAP_ADR_LOC 16
153 +#define PCIE_PHY_CTRL_CAP_DAT_LOC 17
154 +#define PCIE_PHY_CTRL_WR_LOC 18
155 +#define PCIE_PHY_CTRL_RD_LOC 19
156 +
157 +#define PCIE_PHY_STAT (PL_OFFSET + 0x110)
158 +#define PCIE_PHY_STAT_ACK_LOC 16
159 +
160 +/* PHY registers (not memory-mapped) */
161 +#define PCIE_PHY_RX_ASIC_OUT 0x100D
162 +
163 +#define PHY_RX_OVRD_IN_LO 0x1005
164 +#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
165 +#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
166 +
167 +static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
168 +{
169 +       u32 val;
170 +       u32 max_iterations = 10;
171 +       u32 wait_counter = 0;
172 +
173 +       do {
174 +               val = readl(dbi_base + PCIE_PHY_STAT);
175 +               val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
176 +               wait_counter++;
177 +
178 +               if (val == exp_val)
179 +                       return 0;
180 +
181 +               udelay(1);
182 +       } while ((wait_counter < max_iterations) && (val != exp_val));
183 +
184 +       return -ETIMEDOUT;
185 +}
186 +
187 +static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
188 +{
189 +       u32 val;
190 +       int ret;
191 +
192 +       val = addr << PCIE_PHY_CTRL_DATA_LOC;
193 +       writel(val, dbi_base + PCIE_PHY_CTRL);
194 +
195 +       val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
196 +       writel(val, dbi_base + PCIE_PHY_CTRL);
197 +
198 +       ret = pcie_phy_poll_ack(dbi_base, 1);
199 +       if (ret)
200 +               return ret;
201 +
202 +       val = addr << PCIE_PHY_CTRL_DATA_LOC;
203 +       writel(val, dbi_base + PCIE_PHY_CTRL);
204 +
205 +       ret = pcie_phy_poll_ack(dbi_base, 0);
206 +       if (ret)
207 +               return ret;
208 +
209 +       return 0;
210 +}
211 +
212 +/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
213 +static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
214 +{
215 +       u32 val, phy_ctl;
216 +       int ret;
217 +
218 +       ret = pcie_phy_wait_ack(dbi_base, addr);
219 +       if (ret)
220 +               return ret;
221 +
222 +       /* assert Read signal */
223 +       phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
224 +       writel(phy_ctl, dbi_base + PCIE_PHY_CTRL);
225 +
226 +       ret = pcie_phy_poll_ack(dbi_base, 1);
227 +       if (ret)
228 +               return ret;
229 +
230 +       val = readl(dbi_base + PCIE_PHY_STAT);
231 +       *data = val & 0xffff;
232 +
233 +       /* deassert Read signal */
234 +       writel(0x00, dbi_base + PCIE_PHY_CTRL);
235 +
236 +       ret = pcie_phy_poll_ack(dbi_base, 0);
237 +       if (ret)
238 +               return ret;
239 +
240 +       return 0;
241 +}
242 +
243 +static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
244 +{
245 +       u32 var;
246 +       int ret;
247 +
248 +       /* write addr */
249 +       /* cap addr */
250 +       ret = pcie_phy_wait_ack(dbi_base, addr);
251 +       if (ret)
252 +               return ret;
253 +
254 +       var = data << PCIE_PHY_CTRL_DATA_LOC;
255 +       writel(var, dbi_base + PCIE_PHY_CTRL);
256 +
257 +       /* capture data */
258 +       var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
259 +       writel(var, dbi_base + PCIE_PHY_CTRL);
260 +
261 +       ret = pcie_phy_poll_ack(dbi_base, 1);
262 +       if (ret)
263 +               return ret;
264 +
265 +       /* deassert cap data */
266 +       var = data << PCIE_PHY_CTRL_DATA_LOC;
267 +       writel(var, dbi_base + PCIE_PHY_CTRL);
268 +
269 +       /* wait for ack de-assetion */
270 +       ret = pcie_phy_poll_ack(dbi_base, 0);
271 +       if (ret)
272 +               return ret;
273 +
274 +       /* assert wr signal */
275 +       var = 0x1 << PCIE_PHY_CTRL_WR_LOC;
276 +       writel(var, dbi_base + PCIE_PHY_CTRL);
277 +
278 +       /* wait for ack */
279 +       ret = pcie_phy_poll_ack(dbi_base, 1);
280 +       if (ret)
281 +               return ret;
282 +
283 +       /* deassert wr signal */
284 +       var = data << PCIE_PHY_CTRL_DATA_LOC;
285 +       writel(var, dbi_base + PCIE_PHY_CTRL);
286 +
287 +       /* wait for ack de-assetion */
288 +       ret = pcie_phy_poll_ack(dbi_base, 0);
289 +       if (ret)
290 +               return ret;
291 +
292 +       writel(0x0, dbi_base + PCIE_PHY_CTRL);
293 +
294 +       return 0;
295 +}
296 +
297 +/*  Added for PCI abort handling */
298 +static int imx6q_pcie_abort_handler(unsigned long addr,
299 +               unsigned int fsr, struct pt_regs *regs)
300 +{
301 +       /*
302 +        * If it was an imprecise abort, then we need to correct the
303 +        * return address to be _after_ the instruction.
304 +        */
305 +       if (fsr & (1 << 10))
306 +               regs->ARM_pc += 4;
307 +       return 0;
308 +}
309 +
310 +static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
311 +{
312 +       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
313 +
314 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
315 +                       IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
316 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
317 +                       IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
318 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
319 +                       IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
320 +
321 +       gpio_set_value(imx6_pcie->reset_gpio, 0);
322 +       msleep(100);
323 +       gpio_set_value(imx6_pcie->reset_gpio, 1);
324 +
325 +       return 0;
326 +}
327 +
328 +static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
329 +{
330 +       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
331 +       int ret;
332 +
333 +       if (gpio_is_valid(imx6_pcie->power_on_gpio))
334 +               gpio_set_value(imx6_pcie->power_on_gpio, 1);
335 +
336 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
337 +                       IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
338 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
339 +                       IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
340 +
341 +       ret = clk_prepare_enable(imx6_pcie->sata_ref_100m);
342 +       if (ret) {
343 +               dev_err(pp->dev, "unable to enable sata_ref_100m\n");
344 +               goto err_sata_ref;
345 +       }
346 +
347 +       ret = clk_prepare_enable(imx6_pcie->pcie_ref_125m);
348 +       if (ret) {
349 +               dev_err(pp->dev, "unable to enable pcie_ref_125m\n");
350 +               goto err_pcie_ref;
351 +       }
352 +
353 +       ret = clk_prepare_enable(imx6_pcie->lvds_gate);
354 +       if (ret) {
355 +               dev_err(pp->dev, "unable to enable lvds_gate\n");
356 +               goto err_lvds_gate;
357 +       }
358 +
359 +       ret = clk_prepare_enable(imx6_pcie->pcie_axi);
360 +       if (ret) {
361 +               dev_err(pp->dev, "unable to enable pcie_axi\n");
362 +               goto err_pcie_axi;
363 +       }
364 +
365 +       /* allow the clocks to stabilize */
366 +       usleep_range(200, 500);
367 +
368 +       return 0;
369 +
370 +err_pcie_axi:
371 +       clk_disable_unprepare(imx6_pcie->lvds_gate);
372 +err_lvds_gate:
373 +       clk_disable_unprepare(imx6_pcie->pcie_ref_125m);
374 +err_pcie_ref:
375 +       clk_disable_unprepare(imx6_pcie->sata_ref_100m);
376 +err_sata_ref:
377 +       return ret;
378 +
379 +}
380 +
381 +static void imx6_pcie_init_phy(struct pcie_port *pp)
382 +{
383 +       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
384 +
385 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
386 +                       IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
387 +
388 +       /* configure constant input signal to the pcie ctrl and phy */
389 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
390 +                       IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
391 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
392 +                       IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
393 +
394 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
395 +                       IMX6Q_GPR8_TX_DEEMPH_GEN1, 0 << 0);
396 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
397 +                       IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6);
398 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
399 +                       IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12);
400 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
401 +                       IMX6Q_GPR8_TX_SWING_FULL, 127 << 18);
402 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
403 +                       IMX6Q_GPR8_TX_SWING_LOW, 127 << 25);
404 +}
405 +
406 +static void imx6_pcie_host_init(struct pcie_port *pp)
407 +{
408 +       int count = 0;
409 +       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
410 +
411 +       imx6_pcie_assert_core_reset(pp);
412 +
413 +       imx6_pcie_init_phy(pp);
414 +
415 +       imx6_pcie_deassert_core_reset(pp);
416 +
417 +       dw_pcie_setup_rc(pp);
418 +
419 +       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
420 +                       IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
421 +
422 +       while (!dw_pcie_link_up(pp)) {
423 +               usleep_range(100, 1000);
424 +               count++;
425 +               if (count >= 10) {
426 +                       dev_err(pp->dev, "phy link never came up\n");
427 +                       dev_dbg(pp->dev,
428 +                               "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
429 +                               readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
430 +                               readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
431 +                       break;
432 +               }
433 +       }
434 +
435 +       return;
436 +}
437 +
438 +static int imx6_pcie_link_up(struct pcie_port *pp)
439 +{
440 +       u32 rc, ltssm, rx_valid, temp;
441 +
442 +       /* link is debug bit 36, debug register 1 starts at bit 32 */
443 +       rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32));
444 +       if (rc)
445 +               return -EAGAIN;
446 +
447 +       /*
448 +        * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
449 +        * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
450 +        * If (MAC/LTSSM.state == Recovery.RcvrLock)
451 +        * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition
452 +        * to gen2 is stuck
453 +        */
454 +       pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
455 +       ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F;
456 +
457 +       if (rx_valid & 0x01)
458 +               return 0;
459 +
460 +       if (ltssm != 0x0d)
461 +               return 0;
462 +
463 +       dev_err(pp->dev,
464 +               "transition to gen2 is stuck, reset PHY!\n");
465 +
466 +       pcie_phy_read(pp->dbi_base,
467 +               PHY_RX_OVRD_IN_LO, &temp);
468 +       temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN
469 +               | PHY_RX_OVRD_IN_LO_RX_PLL_EN);
470 +       pcie_phy_write(pp->dbi_base,
471 +               PHY_RX_OVRD_IN_LO, temp);
472 +
473 +       usleep_range(2000, 3000);
474 +
475 +       pcie_phy_read(pp->dbi_base,
476 +               PHY_RX_OVRD_IN_LO, &temp);
477 +       temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN
478 +               | PHY_RX_OVRD_IN_LO_RX_PLL_EN);
479 +       pcie_phy_write(pp->dbi_base,
480 +               PHY_RX_OVRD_IN_LO, temp);
481 +
482 +       return 0;
483 +}
484 +
485 +static struct pcie_host_ops imx6_pcie_host_ops = {
486 +       .link_up = imx6_pcie_link_up,
487 +       .host_init = imx6_pcie_host_init,
488 +};
489 +
490 +static int imx6_add_pcie_port(struct pcie_port *pp,
491 +                       struct platform_device *pdev)
492 +{
493 +       int ret;
494 +
495 +       pp->irq = platform_get_irq(pdev, 0);
496 +       if (!pp->irq) {
497 +               dev_err(&pdev->dev, "failed to get irq\n");
498 +               return -ENODEV;
499 +       }
500 +
501 +       pp->root_bus_nr = -1;
502 +       pp->ops = &imx6_pcie_host_ops;
503 +
504 +       spin_lock_init(&pp->conf_lock);
505 +       ret = dw_pcie_host_init(pp);
506 +       if (ret) {
507 +               dev_err(&pdev->dev, "failed to initialize host\n");
508 +               return ret;
509 +       }
510 +
511 +       return 0;
512 +}
513 +
514 +static int __init imx6_pcie_probe(struct platform_device *pdev)
515 +{
516 +       struct imx6_pcie *imx6_pcie;
517 +       struct pcie_port *pp;
518 +       struct device_node *np = pdev->dev.of_node;
519 +       struct resource *dbi_base;
520 +       int ret;
521 +
522 +       imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL);
523 +       if (!imx6_pcie)
524 +               return -ENOMEM;
525 +
526 +       pp = &imx6_pcie->pp;
527 +       pp->dev = &pdev->dev;
528 +
529 +       /* Added for PCI abort handling */
530 +       hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
531 +               "imprecise external abort");
532 +
533 +       dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
534 +       if (!dbi_base) {
535 +               dev_err(&pdev->dev, "dbi_base memory resource not found\n");
536 +               return -ENODEV;
537 +       }
538 +
539 +       pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
540 +       if (IS_ERR(pp->dbi_base)) {
541 +               dev_err(&pdev->dev, "unable to remap dbi_base\n");
542 +               ret = PTR_ERR(pp->dbi_base);
543 +               goto err;
544 +       }
545 +
546 +       /* Fetch GPIOs */
547 +       imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
548 +       if (!gpio_is_valid(imx6_pcie->reset_gpio)) {
549 +               dev_err(&pdev->dev, "no reset-gpio defined\n");
550 +               ret = -ENODEV;
551 +       }
552 +       ret = devm_gpio_request_one(&pdev->dev,
553 +                               imx6_pcie->reset_gpio,
554 +                               GPIOF_OUT_INIT_LOW,
555 +                               "PCIe reset");
556 +       if (ret) {
557 +               dev_err(&pdev->dev, "unable to get reset gpio\n");
558 +               goto err;
559 +       }
560 +
561 +       imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0);
562 +       if (gpio_is_valid(imx6_pcie->power_on_gpio)) {
563 +               ret = devm_gpio_request_one(&pdev->dev,
564 +                                       imx6_pcie->power_on_gpio,
565 +                                       GPIOF_OUT_INIT_LOW,
566 +                                       "PCIe power enable");
567 +               if (ret) {
568 +                       dev_err(&pdev->dev, "unable to get power-on gpio\n");
569 +                       goto err;
570 +               }
571 +       }
572 +
573 +       imx6_pcie->wake_up_gpio = of_get_named_gpio(np, "wake-up-gpio", 0);
574 +       if (gpio_is_valid(imx6_pcie->wake_up_gpio)) {
575 +               ret = devm_gpio_request_one(&pdev->dev,
576 +                                       imx6_pcie->wake_up_gpio,
577 +                                       GPIOF_IN,
578 +                                       "PCIe wake up");
579 +               if (ret) {
580 +                       dev_err(&pdev->dev, "unable to get wake-up gpio\n");
581 +                       goto err;
582 +               }
583 +       }
584 +
585 +       imx6_pcie->disable_gpio = of_get_named_gpio(np, "disable-gpio", 0);
586 +       if (gpio_is_valid(imx6_pcie->disable_gpio)) {
587 +               ret = devm_gpio_request_one(&pdev->dev,
588 +                                       imx6_pcie->disable_gpio,
589 +                                       GPIOF_OUT_INIT_HIGH,
590 +                                       "PCIe disable endpoint");
591 +               if (ret) {
592 +                       dev_err(&pdev->dev, "unable to get disable-ep gpio\n");
593 +                       goto err;
594 +               }
595 +       }
596 +
597 +       /* Fetch clocks */
598 +       imx6_pcie->lvds_gate = clk_get(&pdev->dev, "lvds_gate");
599 +       if (IS_ERR(imx6_pcie->lvds_gate)) {
600 +               dev_err(&pdev->dev,
601 +                       "lvds_gate clock select missing or invalid\n");
602 +               ret = PTR_ERR(imx6_pcie->lvds_gate);
603 +               goto err;
604 +       }
605 +
606 +       imx6_pcie->sata_ref_100m = clk_get(&pdev->dev, "sata_ref_100m");
607 +       if (IS_ERR(imx6_pcie->sata_ref_100m)) {
608 +               dev_err(&pdev->dev,
609 +                       "sata_ref_100m clock source missing or invalid\n");
610 +               ret = PTR_ERR(imx6_pcie->sata_ref_100m);
611 +               goto err;
612 +       }
613 +
614 +       imx6_pcie->pcie_ref_125m = clk_get(&pdev->dev, "pcie_ref_125m");
615 +       if (IS_ERR(imx6_pcie->pcie_ref_125m)) {
616 +               dev_err(&pdev->dev,
617 +                       "pcie_ref_125m clock source missing or invalid\n");
618 +               ret = PTR_ERR(imx6_pcie->pcie_ref_125m);
619 +               goto err;
620 +       }
621 +
622 +       imx6_pcie->pcie_axi = clk_get(&pdev->dev, "pcie_axi");
623 +       if (IS_ERR(imx6_pcie->pcie_axi)) {
624 +               dev_err(&pdev->dev,
625 +                       "pcie_axi clock source missing or invalid\n");
626 +               ret = PTR_ERR(imx6_pcie->pcie_axi);
627 +               goto err;
628 +       }
629 +
630 +       /* Grab GPR config register range */
631 +       imx6_pcie->iomuxc_gpr =
632 +                syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
633 +       if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
634 +               dev_err(&pdev->dev, "unable to find iomuxc registers\n");
635 +               ret = PTR_ERR(imx6_pcie->iomuxc_gpr);
636 +               goto err;
637 +       }
638 +
639 +       ret = imx6_add_pcie_port(pp, pdev);
640 +       if (ret < 0)
641 +               goto err;
642 +
643 +       platform_set_drvdata(pdev, imx6_pcie);
644 +       return 0;
645 +
646 +err:
647 +       return ret;
648 +}
649 +
650 +static const struct of_device_id imx6_pcie_of_match[] = {
651 +       { .compatible = "fsl,imx6q-pcie", },
652 +       {},
653 +};
654 +MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);
655 +
656 +static struct platform_driver imx6_pcie_driver = {
657 +       .driver = {
658 +               .name   = "imx6q-pcie",
659 +               .owner  = THIS_MODULE,
660 +               .of_match_table = of_match_ptr(imx6_pcie_of_match),
661 +       },
662 +};
663 +
664 +/* Freescale PCIe driver does not allow module unload */
665 +
666 +static int __init imx6_init(void)
667 +{
668 +       return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe);
669 +}
670 +module_init(imx6_init);
671 +
672 +MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
673 +MODULE_DESCRIPTION("Freescale i.MX6 PCIe host controller driver");
674 +MODULE_LICENSE("GPL v2");