diff options
Diffstat (limited to 'drivers/pci/controller/dwc/pci-imx6.c')
-rw-r--r-- | drivers/pci/controller/dwc/pci-imx6.c | 224 |
1 files changed, 202 insertions, 22 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 80f843030e36..3d627f94a166 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Author: Sean Cross <xobs@kosagi.com> | 8 | * Author: Sean Cross <xobs@kosagi.com> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/bitfield.h> | ||
11 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
12 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
13 | #include <linux/gpio.h> | 14 | #include <linux/gpio.h> |
@@ -18,6 +19,7 @@ | |||
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/of_gpio.h> | 20 | #include <linux/of_gpio.h> |
20 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
22 | #include <linux/of_address.h> | ||
21 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
22 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
23 | #include <linux/regmap.h> | 25 | #include <linux/regmap.h> |
@@ -32,6 +34,12 @@ | |||
32 | 34 | ||
33 | #include "pcie-designware.h" | 35 | #include "pcie-designware.h" |
34 | 36 | ||
37 | #define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9) | ||
38 | #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10) | ||
39 | #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE BIT(11) | ||
40 | #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE GENMASK(11, 8) | ||
41 | #define IMX8MQ_PCIE2_BASE_ADDR 0x33c00000 | ||
42 | |||
35 | #define to_imx6_pcie(x) dev_get_drvdata((x)->dev) | 43 | #define to_imx6_pcie(x) dev_get_drvdata((x)->dev) |
36 | 44 | ||
37 | enum imx6_pcie_variants { | 45 | enum imx6_pcie_variants { |
@@ -39,6 +47,15 @@ enum imx6_pcie_variants { | |||
39 | IMX6SX, | 47 | IMX6SX, |
40 | IMX6QP, | 48 | IMX6QP, |
41 | IMX7D, | 49 | IMX7D, |
50 | IMX8MQ, | ||
51 | }; | ||
52 | |||
53 | #define IMX6_PCIE_FLAG_IMX6_PHY BIT(0) | ||
54 | #define IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE BIT(1) | ||
55 | |||
56 | struct imx6_pcie_drvdata { | ||
57 | enum imx6_pcie_variants variant; | ||
58 | u32 flags; | ||
42 | }; | 59 | }; |
43 | 60 | ||
44 | struct imx6_pcie { | 61 | struct imx6_pcie { |
@@ -49,11 +66,12 @@ struct imx6_pcie { | |||
49 | struct clk *pcie_phy; | 66 | struct clk *pcie_phy; |
50 | struct clk *pcie_inbound_axi; | 67 | struct clk *pcie_inbound_axi; |
51 | struct clk *pcie; | 68 | struct clk *pcie; |
69 | struct clk *pcie_aux; | ||
52 | struct regmap *iomuxc_gpr; | 70 | struct regmap *iomuxc_gpr; |
71 | u32 controller_id; | ||
53 | struct reset_control *pciephy_reset; | 72 | struct reset_control *pciephy_reset; |
54 | struct reset_control *apps_reset; | 73 | struct reset_control *apps_reset; |
55 | struct reset_control *turnoff_reset; | 74 | struct reset_control *turnoff_reset; |
56 | enum imx6_pcie_variants variant; | ||
57 | u32 tx_deemph_gen1; | 75 | u32 tx_deemph_gen1; |
58 | u32 tx_deemph_gen2_3p5db; | 76 | u32 tx_deemph_gen2_3p5db; |
59 | u32 tx_deemph_gen2_6db; | 77 | u32 tx_deemph_gen2_6db; |
@@ -61,11 +79,13 @@ struct imx6_pcie { | |||
61 | u32 tx_swing_low; | 79 | u32 tx_swing_low; |
62 | int link_gen; | 80 | int link_gen; |
63 | struct regulator *vpcie; | 81 | struct regulator *vpcie; |
82 | void __iomem *phy_base; | ||
64 | 83 | ||
65 | /* power domain for pcie */ | 84 | /* power domain for pcie */ |
66 | struct device *pd_pcie; | 85 | struct device *pd_pcie; |
67 | /* power domain for pcie phy */ | 86 | /* power domain for pcie phy */ |
68 | struct device *pd_pcie_phy; | 87 | struct device *pd_pcie_phy; |
88 | const struct imx6_pcie_drvdata *drvdata; | ||
69 | }; | 89 | }; |
70 | 90 | ||
71 | /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ | 91 | /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ |
@@ -101,7 +121,6 @@ struct imx6_pcie { | |||
101 | #define PCIE_PHY_STAT_ACK_LOC 16 | 121 | #define PCIE_PHY_STAT_ACK_LOC 16 |
102 | 122 | ||
103 | #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C | 123 | #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C |
104 | #define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) | ||
105 | 124 | ||
106 | /* PHY registers (not memory-mapped) */ | 125 | /* PHY registers (not memory-mapped) */ |
107 | #define PCIE_PHY_ATEOVRD 0x10 | 126 | #define PCIE_PHY_ATEOVRD 0x10 |
@@ -117,6 +136,23 @@ struct imx6_pcie { | |||
117 | #define PCIE_PHY_RX_ASIC_OUT 0x100D | 136 | #define PCIE_PHY_RX_ASIC_OUT 0x100D |
118 | #define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0) | 137 | #define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0) |
119 | 138 | ||
139 | /* iMX7 PCIe PHY registers */ | ||
140 | #define PCIE_PHY_CMN_REG4 0x14 | ||
141 | /* These are probably the bits that *aren't* DCC_FB_EN */ | ||
142 | #define PCIE_PHY_CMN_REG4_DCC_FB_EN 0x29 | ||
143 | |||
144 | #define PCIE_PHY_CMN_REG15 0x54 | ||
145 | #define PCIE_PHY_CMN_REG15_DLY_4 BIT(2) | ||
146 | #define PCIE_PHY_CMN_REG15_PLL_PD BIT(5) | ||
147 | #define PCIE_PHY_CMN_REG15_OVRD_PLL_PD BIT(7) | ||
148 | |||
149 | #define PCIE_PHY_CMN_REG24 0x90 | ||
150 | #define PCIE_PHY_CMN_REG24_RX_EQ BIT(6) | ||
151 | #define PCIE_PHY_CMN_REG24_RX_EQ_SEL BIT(3) | ||
152 | |||
153 | #define PCIE_PHY_CMN_REG26 0x98 | ||
154 | #define PCIE_PHY_CMN_REG26_ATT_MODE 0xBC | ||
155 | |||
120 | #define PHY_RX_OVRD_IN_LO 0x1005 | 156 | #define PHY_RX_OVRD_IN_LO 0x1005 |
121 | #define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) | 157 | #define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) |
122 | #define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3) | 158 | #define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3) |
@@ -251,6 +287,9 @@ static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie) | |||
251 | { | 287 | { |
252 | u32 tmp; | 288 | u32 tmp; |
253 | 289 | ||
290 | if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY)) | ||
291 | return; | ||
292 | |||
254 | pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp); | 293 | pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp); |
255 | tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | | 294 | tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | |
256 | PHY_RX_OVRD_IN_LO_RX_PLL_EN); | 295 | PHY_RX_OVRD_IN_LO_RX_PLL_EN); |
@@ -264,6 +303,7 @@ static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie) | |||
264 | pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp); | 303 | pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp); |
265 | } | 304 | } |
266 | 305 | ||
306 | #ifdef CONFIG_ARM | ||
267 | /* Added for PCI abort handling */ | 307 | /* Added for PCI abort handling */ |
268 | static int imx6q_pcie_abort_handler(unsigned long addr, | 308 | static int imx6q_pcie_abort_handler(unsigned long addr, |
269 | unsigned int fsr, struct pt_regs *regs) | 309 | unsigned int fsr, struct pt_regs *regs) |
@@ -297,6 +337,7 @@ static int imx6q_pcie_abort_handler(unsigned long addr, | |||
297 | 337 | ||
298 | return 1; | 338 | return 1; |
299 | } | 339 | } |
340 | #endif | ||
300 | 341 | ||
301 | static int imx6_pcie_attach_pd(struct device *dev) | 342 | static int imx6_pcie_attach_pd(struct device *dev) |
302 | { | 343 | { |
@@ -342,8 +383,9 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) | |||
342 | { | 383 | { |
343 | struct device *dev = imx6_pcie->pci->dev; | 384 | struct device *dev = imx6_pcie->pci->dev; |
344 | 385 | ||
345 | switch (imx6_pcie->variant) { | 386 | switch (imx6_pcie->drvdata->variant) { |
346 | case IMX7D: | 387 | case IMX7D: |
388 | case IMX8MQ: | ||
347 | reset_control_assert(imx6_pcie->pciephy_reset); | 389 | reset_control_assert(imx6_pcie->pciephy_reset); |
348 | reset_control_assert(imx6_pcie->apps_reset); | 390 | reset_control_assert(imx6_pcie->apps_reset); |
349 | break; | 391 | break; |
@@ -378,13 +420,20 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) | |||
378 | } | 420 | } |
379 | } | 421 | } |
380 | 422 | ||
423 | static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie) | ||
424 | { | ||
425 | WARN_ON(imx6_pcie->drvdata->variant != IMX8MQ); | ||
426 | return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14; | ||
427 | } | ||
428 | |||
381 | static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) | 429 | static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) |
382 | { | 430 | { |
383 | struct dw_pcie *pci = imx6_pcie->pci; | 431 | struct dw_pcie *pci = imx6_pcie->pci; |
384 | struct device *dev = pci->dev; | 432 | struct device *dev = pci->dev; |
433 | unsigned int offset; | ||
385 | int ret = 0; | 434 | int ret = 0; |
386 | 435 | ||
387 | switch (imx6_pcie->variant) { | 436 | switch (imx6_pcie->drvdata->variant) { |
388 | case IMX6SX: | 437 | case IMX6SX: |
389 | ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi); | 438 | ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi); |
390 | if (ret) { | 439 | if (ret) { |
@@ -412,6 +461,25 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) | |||
412 | break; | 461 | break; |
413 | case IMX7D: | 462 | case IMX7D: |
414 | break; | 463 | break; |
464 | case IMX8MQ: | ||
465 | ret = clk_prepare_enable(imx6_pcie->pcie_aux); | ||
466 | if (ret) { | ||
467 | dev_err(dev, "unable to enable pcie_aux clock\n"); | ||
468 | break; | ||
469 | } | ||
470 | |||
471 | offset = imx6_pcie_grp_offset(imx6_pcie); | ||
472 | /* | ||
473 | * Set the over ride low and enabled | ||
474 | * make sure that REF_CLK is turned on. | ||
475 | */ | ||
476 | regmap_update_bits(imx6_pcie->iomuxc_gpr, offset, | ||
477 | IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE, | ||
478 | 0); | ||
479 | regmap_update_bits(imx6_pcie->iomuxc_gpr, offset, | ||
480 | IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, | ||
481 | IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN); | ||
482 | break; | ||
415 | } | 483 | } |
416 | 484 | ||
417 | return ret; | 485 | return ret; |
@@ -487,9 +555,32 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) | |||
487 | !imx6_pcie->gpio_active_high); | 555 | !imx6_pcie->gpio_active_high); |
488 | } | 556 | } |
489 | 557 | ||
490 | switch (imx6_pcie->variant) { | 558 | switch (imx6_pcie->drvdata->variant) { |
559 | case IMX8MQ: | ||
560 | reset_control_deassert(imx6_pcie->pciephy_reset); | ||
561 | break; | ||
491 | case IMX7D: | 562 | case IMX7D: |
492 | reset_control_deassert(imx6_pcie->pciephy_reset); | 563 | reset_control_deassert(imx6_pcie->pciephy_reset); |
564 | |||
565 | /* Workaround for ERR010728, failure of PCI-e PLL VCO to | ||
566 | * oscillate, especially when cold. This turns off "Duty-cycle | ||
567 | * Corrector" and other mysterious undocumented things. | ||
568 | */ | ||
569 | if (likely(imx6_pcie->phy_base)) { | ||
570 | /* De-assert DCC_FB_EN */ | ||
571 | writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, | ||
572 | imx6_pcie->phy_base + PCIE_PHY_CMN_REG4); | ||
573 | /* Assert RX_EQS and RX_EQS_SEL */ | ||
574 | writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL | ||
575 | | PCIE_PHY_CMN_REG24_RX_EQ, | ||
576 | imx6_pcie->phy_base + PCIE_PHY_CMN_REG24); | ||
577 | /* Assert ATT_MODE */ | ||
578 | writel(PCIE_PHY_CMN_REG26_ATT_MODE, | ||
579 | imx6_pcie->phy_base + PCIE_PHY_CMN_REG26); | ||
580 | } else { | ||
581 | dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n"); | ||
582 | } | ||
583 | |||
493 | imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie); | 584 | imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie); |
494 | break; | 585 | break; |
495 | case IMX6SX: | 586 | case IMX6SX: |
@@ -523,9 +614,37 @@ err_pcie_phy: | |||
523 | } | 614 | } |
524 | } | 615 | } |
525 | 616 | ||
617 | static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie) | ||
618 | { | ||
619 | unsigned int mask, val; | ||
620 | |||
621 | if (imx6_pcie->drvdata->variant == IMX8MQ && | ||
622 | imx6_pcie->controller_id == 1) { | ||
623 | mask = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE; | ||
624 | val = FIELD_PREP(IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, | ||
625 | PCI_EXP_TYPE_ROOT_PORT); | ||
626 | } else { | ||
627 | mask = IMX6Q_GPR12_DEVICE_TYPE; | ||
628 | val = FIELD_PREP(IMX6Q_GPR12_DEVICE_TYPE, | ||
629 | PCI_EXP_TYPE_ROOT_PORT); | ||
630 | } | ||
631 | |||
632 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, mask, val); | ||
633 | } | ||
634 | |||
526 | static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) | 635 | static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) |
527 | { | 636 | { |
528 | switch (imx6_pcie->variant) { | 637 | switch (imx6_pcie->drvdata->variant) { |
638 | case IMX8MQ: | ||
639 | /* | ||
640 | * TODO: Currently this code assumes external | ||
641 | * oscillator is being used | ||
642 | */ | ||
643 | regmap_update_bits(imx6_pcie->iomuxc_gpr, | ||
644 | imx6_pcie_grp_offset(imx6_pcie), | ||
645 | IMX8MQ_GPR_PCIE_REF_USE_PAD, | ||
646 | IMX8MQ_GPR_PCIE_REF_USE_PAD); | ||
647 | break; | ||
529 | case IMX7D: | 648 | case IMX7D: |
530 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | 649 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
531 | IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0); | 650 | IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0); |
@@ -561,8 +680,7 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) | |||
561 | break; | 680 | break; |
562 | } | 681 | } |
563 | 682 | ||
564 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | 683 | imx6_pcie_configure_type(imx6_pcie); |
565 | IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12); | ||
566 | } | 684 | } |
567 | 685 | ||
568 | static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie) | 686 | static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie) |
@@ -571,6 +689,9 @@ static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie) | |||
571 | int mult, div; | 689 | int mult, div; |
572 | u32 val; | 690 | u32 val; |
573 | 691 | ||
692 | if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY)) | ||
693 | return 0; | ||
694 | |||
574 | switch (phy_rate) { | 695 | switch (phy_rate) { |
575 | case 125000000: | 696 | case 125000000: |
576 | /* | 697 | /* |
@@ -647,7 +768,7 @@ static void imx6_pcie_ltssm_enable(struct device *dev) | |||
647 | { | 768 | { |
648 | struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); | 769 | struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); |
649 | 770 | ||
650 | switch (imx6_pcie->variant) { | 771 | switch (imx6_pcie->drvdata->variant) { |
651 | case IMX6Q: | 772 | case IMX6Q: |
652 | case IMX6SX: | 773 | case IMX6SX: |
653 | case IMX6QP: | 774 | case IMX6QP: |
@@ -656,6 +777,7 @@ static void imx6_pcie_ltssm_enable(struct device *dev) | |||
656 | IMX6Q_GPR12_PCIE_CTL_2); | 777 | IMX6Q_GPR12_PCIE_CTL_2); |
657 | break; | 778 | break; |
658 | case IMX7D: | 779 | case IMX7D: |
780 | case IMX8MQ: | ||
659 | reset_control_deassert(imx6_pcie->apps_reset); | 781 | reset_control_deassert(imx6_pcie->apps_reset); |
660 | break; | 782 | break; |
661 | } | 783 | } |
@@ -700,7 +822,8 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) | |||
700 | tmp |= PORT_LOGIC_SPEED_CHANGE; | 822 | tmp |= PORT_LOGIC_SPEED_CHANGE; |
701 | dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); | 823 | dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); |
702 | 824 | ||
703 | if (imx6_pcie->variant != IMX7D) { | 825 | if (imx6_pcie->drvdata->flags & |
826 | IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE) { | ||
704 | /* | 827 | /* |
705 | * On i.MX7, DIRECT_SPEED_CHANGE behaves differently | 828 | * On i.MX7, DIRECT_SPEED_CHANGE behaves differently |
706 | * from i.MX6 family when no link speed transition | 829 | * from i.MX6 family when no link speed transition |
@@ -797,7 +920,7 @@ static void imx6_pcie_ltssm_disable(struct device *dev) | |||
797 | { | 920 | { |
798 | struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); | 921 | struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); |
799 | 922 | ||
800 | switch (imx6_pcie->variant) { | 923 | switch (imx6_pcie->drvdata->variant) { |
801 | case IMX6SX: | 924 | case IMX6SX: |
802 | case IMX6QP: | 925 | case IMX6QP: |
803 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | 926 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
@@ -823,7 +946,7 @@ static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie) | |||
823 | } | 946 | } |
824 | 947 | ||
825 | /* Others poke directly at IOMUXC registers */ | 948 | /* Others poke directly at IOMUXC registers */ |
826 | switch (imx6_pcie->variant) { | 949 | switch (imx6_pcie->drvdata->variant) { |
827 | case IMX6SX: | 950 | case IMX6SX: |
828 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | 951 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
829 | IMX6SX_GPR12_PCIE_PM_TURN_OFF, | 952 | IMX6SX_GPR12_PCIE_PM_TURN_OFF, |
@@ -853,7 +976,7 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie) | |||
853 | clk_disable_unprepare(imx6_pcie->pcie_phy); | 976 | clk_disable_unprepare(imx6_pcie->pcie_phy); |
854 | clk_disable_unprepare(imx6_pcie->pcie_bus); | 977 | clk_disable_unprepare(imx6_pcie->pcie_bus); |
855 | 978 | ||
856 | switch (imx6_pcie->variant) { | 979 | switch (imx6_pcie->drvdata->variant) { |
857 | case IMX6SX: | 980 | case IMX6SX: |
858 | clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); | 981 | clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); |
859 | break; | 982 | break; |
@@ -862,6 +985,9 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie) | |||
862 | IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, | 985 | IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, |
863 | IMX7D_GPR12_PCIE_PHY_REFCLK_SEL); | 986 | IMX7D_GPR12_PCIE_PHY_REFCLK_SEL); |
864 | break; | 987 | break; |
988 | case IMX8MQ: | ||
989 | clk_disable_unprepare(imx6_pcie->pcie_aux); | ||
990 | break; | ||
865 | default: | 991 | default: |
866 | break; | 992 | break; |
867 | } | 993 | } |
@@ -869,8 +995,8 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie) | |||
869 | 995 | ||
870 | static inline bool imx6_pcie_supports_suspend(struct imx6_pcie *imx6_pcie) | 996 | static inline bool imx6_pcie_supports_suspend(struct imx6_pcie *imx6_pcie) |
871 | { | 997 | { |
872 | return (imx6_pcie->variant == IMX7D || | 998 | return (imx6_pcie->drvdata->variant == IMX7D || |
873 | imx6_pcie->variant == IMX6SX); | 999 | imx6_pcie->drvdata->variant == IMX6SX); |
874 | } | 1000 | } |
875 | 1001 | ||
876 | static int imx6_pcie_suspend_noirq(struct device *dev) | 1002 | static int imx6_pcie_suspend_noirq(struct device *dev) |
@@ -919,6 +1045,7 @@ static int imx6_pcie_probe(struct platform_device *pdev) | |||
919 | struct device *dev = &pdev->dev; | 1045 | struct device *dev = &pdev->dev; |
920 | struct dw_pcie *pci; | 1046 | struct dw_pcie *pci; |
921 | struct imx6_pcie *imx6_pcie; | 1047 | struct imx6_pcie *imx6_pcie; |
1048 | struct device_node *np; | ||
922 | struct resource *dbi_base; | 1049 | struct resource *dbi_base; |
923 | struct device_node *node = dev->of_node; | 1050 | struct device_node *node = dev->of_node; |
924 | int ret; | 1051 | int ret; |
@@ -936,8 +1063,24 @@ static int imx6_pcie_probe(struct platform_device *pdev) | |||
936 | pci->ops = &dw_pcie_ops; | 1063 | pci->ops = &dw_pcie_ops; |
937 | 1064 | ||
938 | imx6_pcie->pci = pci; | 1065 | imx6_pcie->pci = pci; |
939 | imx6_pcie->variant = | 1066 | imx6_pcie->drvdata = of_device_get_match_data(dev); |
940 | (enum imx6_pcie_variants)of_device_get_match_data(dev); | 1067 | |
1068 | /* Find the PHY if one is defined, only imx7d uses it */ | ||
1069 | np = of_parse_phandle(node, "fsl,imx7d-pcie-phy", 0); | ||
1070 | if (np) { | ||
1071 | struct resource res; | ||
1072 | |||
1073 | ret = of_address_to_resource(np, 0, &res); | ||
1074 | if (ret) { | ||
1075 | dev_err(dev, "Unable to map PCIe PHY\n"); | ||
1076 | return ret; | ||
1077 | } | ||
1078 | imx6_pcie->phy_base = devm_ioremap_resource(dev, &res); | ||
1079 | if (IS_ERR(imx6_pcie->phy_base)) { | ||
1080 | dev_err(dev, "Unable to map PCIe PHY\n"); | ||
1081 | return PTR_ERR(imx6_pcie->phy_base); | ||
1082 | } | ||
1083 | } | ||
941 | 1084 | ||
942 | dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1085 | dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
943 | pci->dbi_base = devm_ioremap_resource(dev, dbi_base); | 1086 | pci->dbi_base = devm_ioremap_resource(dev, dbi_base); |
@@ -981,7 +1124,7 @@ static int imx6_pcie_probe(struct platform_device *pdev) | |||
981 | return PTR_ERR(imx6_pcie->pcie); | 1124 | return PTR_ERR(imx6_pcie->pcie); |
982 | } | 1125 | } |
983 | 1126 | ||
984 | switch (imx6_pcie->variant) { | 1127 | switch (imx6_pcie->drvdata->variant) { |
985 | case IMX6SX: | 1128 | case IMX6SX: |
986 | imx6_pcie->pcie_inbound_axi = devm_clk_get(dev, | 1129 | imx6_pcie->pcie_inbound_axi = devm_clk_get(dev, |
987 | "pcie_inbound_axi"); | 1130 | "pcie_inbound_axi"); |
@@ -990,7 +1133,17 @@ static int imx6_pcie_probe(struct platform_device *pdev) | |||
990 | return PTR_ERR(imx6_pcie->pcie_inbound_axi); | 1133 | return PTR_ERR(imx6_pcie->pcie_inbound_axi); |
991 | } | 1134 | } |
992 | break; | 1135 | break; |
1136 | case IMX8MQ: | ||
1137 | imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux"); | ||
1138 | if (IS_ERR(imx6_pcie->pcie_aux)) { | ||
1139 | dev_err(dev, "pcie_aux clock source missing or invalid\n"); | ||
1140 | return PTR_ERR(imx6_pcie->pcie_aux); | ||
1141 | } | ||
1142 | /* fall through */ | ||
993 | case IMX7D: | 1143 | case IMX7D: |
1144 | if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) | ||
1145 | imx6_pcie->controller_id = 1; | ||
1146 | |||
994 | imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev, | 1147 | imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev, |
995 | "pciephy"); | 1148 | "pciephy"); |
996 | if (IS_ERR(imx6_pcie->pciephy_reset)) { | 1149 | if (IS_ERR(imx6_pcie->pciephy_reset)) { |
@@ -1087,11 +1240,36 @@ static void imx6_pcie_shutdown(struct platform_device *pdev) | |||
1087 | imx6_pcie_assert_core_reset(imx6_pcie); | 1240 | imx6_pcie_assert_core_reset(imx6_pcie); |
1088 | } | 1241 | } |
1089 | 1242 | ||
1243 | static const struct imx6_pcie_drvdata drvdata[] = { | ||
1244 | [IMX6Q] = { | ||
1245 | .variant = IMX6Q, | ||
1246 | .flags = IMX6_PCIE_FLAG_IMX6_PHY | | ||
1247 | IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, | ||
1248 | }, | ||
1249 | [IMX6SX] = { | ||
1250 | .variant = IMX6SX, | ||
1251 | .flags = IMX6_PCIE_FLAG_IMX6_PHY | | ||
1252 | IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, | ||
1253 | }, | ||
1254 | [IMX6QP] = { | ||
1255 | .variant = IMX6QP, | ||
1256 | .flags = IMX6_PCIE_FLAG_IMX6_PHY | | ||
1257 | IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, | ||
1258 | }, | ||
1259 | [IMX7D] = { | ||
1260 | .variant = IMX7D, | ||
1261 | }, | ||
1262 | [IMX8MQ] = { | ||
1263 | .variant = IMX8MQ, | ||
1264 | }, | ||
1265 | }; | ||
1266 | |||
1090 | static const struct of_device_id imx6_pcie_of_match[] = { | 1267 | static const struct of_device_id imx6_pcie_of_match[] = { |
1091 | { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, }, | 1268 | { .compatible = "fsl,imx6q-pcie", .data = &drvdata[IMX6Q], }, |
1092 | { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, }, | 1269 | { .compatible = "fsl,imx6sx-pcie", .data = &drvdata[IMX6SX], }, |
1093 | { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, | 1270 | { .compatible = "fsl,imx6qp-pcie", .data = &drvdata[IMX6QP], }, |
1094 | { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, }, | 1271 | { .compatible = "fsl,imx7d-pcie", .data = &drvdata[IMX7D], }, |
1272 | { .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], } , | ||
1095 | {}, | 1273 | {}, |
1096 | }; | 1274 | }; |
1097 | 1275 | ||
@@ -1108,6 +1286,7 @@ static struct platform_driver imx6_pcie_driver = { | |||
1108 | 1286 | ||
1109 | static int __init imx6_pcie_init(void) | 1287 | static int __init imx6_pcie_init(void) |
1110 | { | 1288 | { |
1289 | #ifdef CONFIG_ARM | ||
1111 | /* | 1290 | /* |
1112 | * Since probe() can be deferred we need to make sure that | 1291 | * Since probe() can be deferred we need to make sure that |
1113 | * hook_fault_code is not called after __init memory is freed | 1292 | * hook_fault_code is not called after __init memory is freed |
@@ -1117,6 +1296,7 @@ static int __init imx6_pcie_init(void) | |||
1117 | */ | 1296 | */ |
1118 | hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0, | 1297 | hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0, |
1119 | "external abort on non-linefetch"); | 1298 | "external abort on non-linefetch"); |
1299 | #endif | ||
1120 | 1300 | ||
1121 | return platform_driver_register(&imx6_pcie_driver); | 1301 | return platform_driver_register(&imx6_pcie_driver); |
1122 | } | 1302 | } |