aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Cross <xobs@kosagi.com>2013-09-25 23:24:47 -0400
committerBjorn Helgaas <bhelgaas@google.com>2013-09-27 15:17:08 -0400
commitbb38919ec56e0758c3ae56dfc091dcde1391353e (patch)
tree2bfadf7af2bd93e9d34b6a69bdae085bac7b3df9
parent8d6a35fb13406f87d926fffeee0d70360ce3077d (diff)
PCI: imx6: Add support for i.MX6 PCIe controller
Add support for the PCIe port present on the i.MX6 family of controllers. These use the Synopsis Designware core tied to their own PHY. Signed-off-by: Sean Cross <xobs@kosagi.com> Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--Documentation/devicetree/bindings/pci/designware-pcie.txt7
-rw-r--r--drivers/pci/host/Kconfig6
-rw-r--r--drivers/pci/host/Makefile1
-rw-r--r--drivers/pci/host/pci-imx6.c575
4 files changed, 588 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt
index eabcb4b5db6e..dd8d920bcbd6 100644
--- a/Documentation/devicetree/bindings/pci/designware-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/designware-pcie.txt
@@ -3,7 +3,7 @@
3Required properties: 3Required properties:
4- compatible: should contain "snps,dw-pcie" to identify the 4- compatible: should contain "snps,dw-pcie" to identify the
5 core, plus an identifier for the specific instance, such 5 core, plus an identifier for the specific instance, such
6 as "samsung,exynos5440-pcie". 6 as "samsung,exynos5440-pcie" or "fsl,imx6q-pcie".
7- reg: base addresses and lengths of the pcie controller, 7- reg: base addresses and lengths of the pcie controller,
8 the phy controller, additional register for the phy controller. 8 the phy controller, additional register for the phy controller.
9- interrupts: interrupt values for level interrupt, 9- interrupts: interrupt values for level interrupt,
@@ -21,6 +21,11 @@ Required properties:
21- num-lanes: number of lanes to use 21- num-lanes: number of lanes to use
22- reset-gpio: gpio pin number of power good signal 22- reset-gpio: gpio pin number of power good signal
23 23
24Optional properties for fsl,imx6q-pcie
25- power-on-gpio: gpio pin number of power-enable signal
26- wake-up-gpio: gpio pin number of incoming wakeup signal
27- disable-gpio: gpio pin number of outgoing rfkill/endpoint disable signal
28
24Example: 29Example:
25 30
26SoC specific DT Entry: 31SoC specific DT Entry:
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 3d9504811126..efa24d9a3361 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -15,6 +15,12 @@ config PCI_EXYNOS
15 select PCIEPORTBUS 15 select PCIEPORTBUS
16 select PCIE_DW 16 select PCIE_DW
17 17
18config PCI_IMX6
19 bool "Freescale i.MX6 PCIe controller"
20 depends on SOC_IMX6Q
21 select PCIEPORTBUS
22 select PCIE_DW
23
18config PCI_TEGRA 24config PCI_TEGRA
19 bool "NVIDIA Tegra PCIe controller" 25 bool "NVIDIA Tegra PCIe controller"
20 depends on ARCH_TEGRA 26 depends on ARCH_TEGRA
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index c9a997b2690d..287d6a053dda 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -1,4 +1,5 @@
1obj-$(CONFIG_PCIE_DW) += pcie-designware.o 1obj-$(CONFIG_PCIE_DW) += pcie-designware.o
2obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o 2obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
3obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
3obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o 4obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
4obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o 5obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
new file mode 100644
index 000000000000..5afa9226a080
--- /dev/null
+++ b/drivers/pci/host/pci-imx6.c
@@ -0,0 +1,575 @@
1/*
2 * PCIe host controller driver for Freescale i.MX6 SoCs
3 *
4 * Copyright (C) 2013 Kosagi
5 * http://www.kosagi.com
6 *
7 * Author: Sean Cross <xobs@kosagi.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/clk.h>
15#include <linux/delay.h>
16#include <linux/gpio.h>
17#include <linux/kernel.h>
18#include <linux/mfd/syscon.h>
19#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
20#include <linux/module.h>
21#include <linux/of_gpio.h>
22#include <linux/pci.h>
23#include <linux/platform_device.h>
24#include <linux/regmap.h>
25#include <linux/resource.h>
26#include <linux/signal.h>
27#include <linux/types.h>
28
29#include "pcie-designware.h"
30
31#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp)
32
33struct imx6_pcie {
34 int reset_gpio;
35 int power_on_gpio;
36 int wake_up_gpio;
37 int disable_gpio;
38 struct clk *lvds_gate;
39 struct clk *sata_ref_100m;
40 struct clk *pcie_ref_125m;
41 struct clk *pcie_axi;
42 struct pcie_port pp;
43 struct regmap *iomuxc_gpr;
44 void __iomem *mem_base;
45};
46
47/* PCIe Port Logic registers (memory-mapped) */
48#define PL_OFFSET 0x700
49#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
50#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
51
52#define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
53#define PCIE_PHY_CTRL_DATA_LOC 0
54#define PCIE_PHY_CTRL_CAP_ADR_LOC 16
55#define PCIE_PHY_CTRL_CAP_DAT_LOC 17
56#define PCIE_PHY_CTRL_WR_LOC 18
57#define PCIE_PHY_CTRL_RD_LOC 19
58
59#define PCIE_PHY_STAT (PL_OFFSET + 0x110)
60#define PCIE_PHY_STAT_ACK_LOC 16
61
62/* PHY registers (not memory-mapped) */
63#define PCIE_PHY_RX_ASIC_OUT 0x100D
64
65#define PHY_RX_OVRD_IN_LO 0x1005
66#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
67#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
68
69static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
70{
71 u32 val;
72 u32 max_iterations = 10;
73 u32 wait_counter = 0;
74
75 do {
76 val = readl(dbi_base + PCIE_PHY_STAT);
77 val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
78 wait_counter++;
79
80 if (val == exp_val)
81 return 0;
82
83 udelay(1);
84 } while (wait_counter < max_iterations);
85
86 return -ETIMEDOUT;
87}
88
89static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
90{
91 u32 val;
92 int ret;
93
94 val = addr << PCIE_PHY_CTRL_DATA_LOC;
95 writel(val, dbi_base + PCIE_PHY_CTRL);
96
97 val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
98 writel(val, dbi_base + PCIE_PHY_CTRL);
99
100 ret = pcie_phy_poll_ack(dbi_base, 1);
101 if (ret)
102 return ret;
103
104 val = addr << PCIE_PHY_CTRL_DATA_LOC;
105 writel(val, dbi_base + PCIE_PHY_CTRL);
106
107 ret = pcie_phy_poll_ack(dbi_base, 0);
108 if (ret)
109 return ret;
110
111 return 0;
112}
113
114/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
115static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
116{
117 u32 val, phy_ctl;
118 int ret;
119
120 ret = pcie_phy_wait_ack(dbi_base, addr);
121 if (ret)
122 return ret;
123
124 /* assert Read signal */
125 phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
126 writel(phy_ctl, dbi_base + PCIE_PHY_CTRL);
127
128 ret = pcie_phy_poll_ack(dbi_base, 1);
129 if (ret)
130 return ret;
131
132 val = readl(dbi_base + PCIE_PHY_STAT);
133 *data = val & 0xffff;
134
135 /* deassert Read signal */
136 writel(0x00, dbi_base + PCIE_PHY_CTRL);
137
138 ret = pcie_phy_poll_ack(dbi_base, 0);
139 if (ret)
140 return ret;
141
142 return 0;
143}
144
145static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
146{
147 u32 var;
148 int ret;
149
150 /* write addr */
151 /* cap addr */
152 ret = pcie_phy_wait_ack(dbi_base, addr);
153 if (ret)
154 return ret;
155
156 var = data << PCIE_PHY_CTRL_DATA_LOC;
157 writel(var, dbi_base + PCIE_PHY_CTRL);
158
159 /* capture data */
160 var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
161 writel(var, dbi_base + PCIE_PHY_CTRL);
162
163 ret = pcie_phy_poll_ack(dbi_base, 1);
164 if (ret)
165 return ret;
166
167 /* deassert cap data */
168 var = data << PCIE_PHY_CTRL_DATA_LOC;
169 writel(var, dbi_base + PCIE_PHY_CTRL);
170
171 /* wait for ack de-assertion */
172 ret = pcie_phy_poll_ack(dbi_base, 0);
173 if (ret)
174 return ret;
175
176 /* assert wr signal */
177 var = 0x1 << PCIE_PHY_CTRL_WR_LOC;
178 writel(var, dbi_base + PCIE_PHY_CTRL);
179
180 /* wait for ack */
181 ret = pcie_phy_poll_ack(dbi_base, 1);
182 if (ret)
183 return ret;
184
185 /* deassert wr signal */
186 var = data << PCIE_PHY_CTRL_DATA_LOC;
187 writel(var, dbi_base + PCIE_PHY_CTRL);
188
189 /* wait for ack de-assertion */
190 ret = pcie_phy_poll_ack(dbi_base, 0);
191 if (ret)
192 return ret;
193
194 writel(0x0, dbi_base + PCIE_PHY_CTRL);
195
196 return 0;
197}
198
199/* Added for PCI abort handling */
200static int imx6q_pcie_abort_handler(unsigned long addr,
201 unsigned int fsr, struct pt_regs *regs)
202{
203 /*
204 * If it was an imprecise abort, then we need to correct the
205 * return address to be _after_ the instruction.
206 */
207 if (fsr & (1 << 10))
208 regs->ARM_pc += 4;
209 return 0;
210}
211
212static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
213{
214 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
215
216 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
217 IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
218 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
219 IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
220 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
221 IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
222
223 gpio_set_value(imx6_pcie->reset_gpio, 0);
224 msleep(100);
225 gpio_set_value(imx6_pcie->reset_gpio, 1);
226
227 return 0;
228}
229
230static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
231{
232 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
233 int ret;
234
235 if (gpio_is_valid(imx6_pcie->power_on_gpio))
236 gpio_set_value(imx6_pcie->power_on_gpio, 1);
237
238 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
239 IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
240 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
241 IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
242
243 ret = clk_prepare_enable(imx6_pcie->sata_ref_100m);
244 if (ret) {
245 dev_err(pp->dev, "unable to enable sata_ref_100m\n");
246 goto err_sata_ref;
247 }
248
249 ret = clk_prepare_enable(imx6_pcie->pcie_ref_125m);
250 if (ret) {
251 dev_err(pp->dev, "unable to enable pcie_ref_125m\n");
252 goto err_pcie_ref;
253 }
254
255 ret = clk_prepare_enable(imx6_pcie->lvds_gate);
256 if (ret) {
257 dev_err(pp->dev, "unable to enable lvds_gate\n");
258 goto err_lvds_gate;
259 }
260
261 ret = clk_prepare_enable(imx6_pcie->pcie_axi);
262 if (ret) {
263 dev_err(pp->dev, "unable to enable pcie_axi\n");
264 goto err_pcie_axi;
265 }
266
267 /* allow the clocks to stabilize */
268 usleep_range(200, 500);
269
270 return 0;
271
272err_pcie_axi:
273 clk_disable_unprepare(imx6_pcie->lvds_gate);
274err_lvds_gate:
275 clk_disable_unprepare(imx6_pcie->pcie_ref_125m);
276err_pcie_ref:
277 clk_disable_unprepare(imx6_pcie->sata_ref_100m);
278err_sata_ref:
279 return ret;
280
281}
282
283static void imx6_pcie_init_phy(struct pcie_port *pp)
284{
285 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
286
287 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
288 IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
289
290 /* configure constant input signal to the pcie ctrl and phy */
291 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
292 IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
293 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
294 IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
295
296 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
297 IMX6Q_GPR8_TX_DEEMPH_GEN1, 0 << 0);
298 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
299 IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6);
300 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
301 IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12);
302 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
303 IMX6Q_GPR8_TX_SWING_FULL, 127 << 18);
304 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
305 IMX6Q_GPR8_TX_SWING_LOW, 127 << 25);
306}
307
308static void imx6_pcie_host_init(struct pcie_port *pp)
309{
310 int count = 0;
311 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
312
313 imx6_pcie_assert_core_reset(pp);
314
315 imx6_pcie_init_phy(pp);
316
317 imx6_pcie_deassert_core_reset(pp);
318
319 dw_pcie_setup_rc(pp);
320
321 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
322 IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
323
324 while (!dw_pcie_link_up(pp)) {
325 usleep_range(100, 1000);
326 count++;
327 if (count >= 10) {
328 dev_err(pp->dev, "phy link never came up\n");
329 dev_dbg(pp->dev,
330 "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
331 readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
332 readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
333 break;
334 }
335 }
336
337 return;
338}
339
340static int imx6_pcie_link_up(struct pcie_port *pp)
341{
342 u32 rc, ltssm, rx_valid, temp;
343
344 /* link is debug bit 36, debug register 1 starts at bit 32 */
345 rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32));
346 if (rc)
347 return -EAGAIN;
348
349 /*
350 * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
351 * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
352 * If (MAC/LTSSM.state == Recovery.RcvrLock)
353 * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition
354 * to gen2 is stuck
355 */
356 pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
357 ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F;
358
359 if (rx_valid & 0x01)
360 return 0;
361
362 if (ltssm != 0x0d)
363 return 0;
364
365 dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
366
367 pcie_phy_read(pp->dbi_base,
368 PHY_RX_OVRD_IN_LO, &temp);
369 temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN
370 | PHY_RX_OVRD_IN_LO_RX_PLL_EN);
371 pcie_phy_write(pp->dbi_base,
372 PHY_RX_OVRD_IN_LO, temp);
373
374 usleep_range(2000, 3000);
375
376 pcie_phy_read(pp->dbi_base,
377 PHY_RX_OVRD_IN_LO, &temp);
378 temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN
379 | PHY_RX_OVRD_IN_LO_RX_PLL_EN);
380 pcie_phy_write(pp->dbi_base,
381 PHY_RX_OVRD_IN_LO, temp);
382
383 return 0;
384}
385
386static struct pcie_host_ops imx6_pcie_host_ops = {
387 .link_up = imx6_pcie_link_up,
388 .host_init = imx6_pcie_host_init,
389};
390
391static int imx6_add_pcie_port(struct pcie_port *pp,
392 struct platform_device *pdev)
393{
394 int ret;
395
396 pp->irq = platform_get_irq(pdev, 0);
397 if (!pp->irq) {
398 dev_err(&pdev->dev, "failed to get irq\n");
399 return -ENODEV;
400 }
401
402 pp->root_bus_nr = -1;
403 pp->ops = &imx6_pcie_host_ops;
404
405 spin_lock_init(&pp->conf_lock);
406 ret = dw_pcie_host_init(pp);
407 if (ret) {
408 dev_err(&pdev->dev, "failed to initialize host\n");
409 return ret;
410 }
411
412 return 0;
413}
414
415static int __init imx6_pcie_probe(struct platform_device *pdev)
416{
417 struct imx6_pcie *imx6_pcie;
418 struct pcie_port *pp;
419 struct device_node *np = pdev->dev.of_node;
420 struct resource *dbi_base;
421 int ret;
422
423 imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL);
424 if (!imx6_pcie)
425 return -ENOMEM;
426
427 pp = &imx6_pcie->pp;
428 pp->dev = &pdev->dev;
429
430 /* Added for PCI abort handling */
431 hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
432 "imprecise external abort");
433
434 dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
435 if (!dbi_base) {
436 dev_err(&pdev->dev, "dbi_base memory resource not found\n");
437 return -ENODEV;
438 }
439
440 pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
441 if (IS_ERR(pp->dbi_base)) {
442 dev_err(&pdev->dev, "unable to remap dbi_base\n");
443 ret = PTR_ERR(pp->dbi_base);
444 goto err;
445 }
446
447 /* Fetch GPIOs */
448 imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
449 if (!gpio_is_valid(imx6_pcie->reset_gpio)) {
450 dev_err(&pdev->dev, "no reset-gpio defined\n");
451 ret = -ENODEV;
452 }
453 ret = devm_gpio_request_one(&pdev->dev,
454 imx6_pcie->reset_gpio,
455 GPIOF_OUT_INIT_LOW,
456 "PCIe reset");
457 if (ret) {
458 dev_err(&pdev->dev, "unable to get reset gpio\n");
459 goto err;
460 }
461
462 imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0);
463 if (gpio_is_valid(imx6_pcie->power_on_gpio)) {
464 ret = devm_gpio_request_one(&pdev->dev,
465 imx6_pcie->power_on_gpio,
466 GPIOF_OUT_INIT_LOW,
467 "PCIe power enable");
468 if (ret) {
469 dev_err(&pdev->dev, "unable to get power-on gpio\n");
470 goto err;
471 }
472 }
473
474 imx6_pcie->wake_up_gpio = of_get_named_gpio(np, "wake-up-gpio", 0);
475 if (gpio_is_valid(imx6_pcie->wake_up_gpio)) {
476 ret = devm_gpio_request_one(&pdev->dev,
477 imx6_pcie->wake_up_gpio,
478 GPIOF_IN,
479 "PCIe wake up");
480 if (ret) {
481 dev_err(&pdev->dev, "unable to get wake-up gpio\n");
482 goto err;
483 }
484 }
485
486 imx6_pcie->disable_gpio = of_get_named_gpio(np, "disable-gpio", 0);
487 if (gpio_is_valid(imx6_pcie->disable_gpio)) {
488 ret = devm_gpio_request_one(&pdev->dev,
489 imx6_pcie->disable_gpio,
490 GPIOF_OUT_INIT_HIGH,
491 "PCIe disable endpoint");
492 if (ret) {
493 dev_err(&pdev->dev, "unable to get disable-ep gpio\n");
494 goto err;
495 }
496 }
497
498 /* Fetch clocks */
499 imx6_pcie->lvds_gate = devm_clk_get(&pdev->dev, "lvds_gate");
500 if (IS_ERR(imx6_pcie->lvds_gate)) {
501 dev_err(&pdev->dev,
502 "lvds_gate clock select missing or invalid\n");
503 ret = PTR_ERR(imx6_pcie->lvds_gate);
504 goto err;
505 }
506
507 imx6_pcie->sata_ref_100m = devm_clk_get(&pdev->dev, "sata_ref_100m");
508 if (IS_ERR(imx6_pcie->sata_ref_100m)) {
509 dev_err(&pdev->dev,
510 "sata_ref_100m clock source missing or invalid\n");
511 ret = PTR_ERR(imx6_pcie->sata_ref_100m);
512 goto err;
513 }
514
515 imx6_pcie->pcie_ref_125m = devm_clk_get(&pdev->dev, "pcie_ref_125m");
516 if (IS_ERR(imx6_pcie->pcie_ref_125m)) {
517 dev_err(&pdev->dev,
518 "pcie_ref_125m clock source missing or invalid\n");
519 ret = PTR_ERR(imx6_pcie->pcie_ref_125m);
520 goto err;
521 }
522
523 imx6_pcie->pcie_axi = devm_clk_get(&pdev->dev, "pcie_axi");
524 if (IS_ERR(imx6_pcie->pcie_axi)) {
525 dev_err(&pdev->dev,
526 "pcie_axi clock source missing or invalid\n");
527 ret = PTR_ERR(imx6_pcie->pcie_axi);
528 goto err;
529 }
530
531 /* Grab GPR config register range */
532 imx6_pcie->iomuxc_gpr =
533 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
534 if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
535 dev_err(&pdev->dev, "unable to find iomuxc registers\n");
536 ret = PTR_ERR(imx6_pcie->iomuxc_gpr);
537 goto err;
538 }
539
540 ret = imx6_add_pcie_port(pp, pdev);
541 if (ret < 0)
542 goto err;
543
544 platform_set_drvdata(pdev, imx6_pcie);
545 return 0;
546
547err:
548 return ret;
549}
550
551static const struct of_device_id imx6_pcie_of_match[] = {
552 { .compatible = "fsl,imx6q-pcie", },
553 {},
554};
555MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);
556
557static struct platform_driver imx6_pcie_driver = {
558 .driver = {
559 .name = "imx6q-pcie",
560 .owner = THIS_MODULE,
561 .of_match_table = of_match_ptr(imx6_pcie_of_match),
562 },
563};
564
565/* Freescale PCIe driver does not allow module unload */
566
567static int __init imx6_pcie_init(void)
568{
569 return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe);
570}
571module_init(imx6_pcie_init);
572
573MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
574MODULE_DESCRIPTION("Freescale i.MX6 PCIe host controller driver");
575MODULE_LICENSE("GPL v2");