Skip to content

Commit 525fde0

Browse files
committed
Merge branch 'remotes/lorenzo/pci/dwc'
- Support 100MHz/200MHz refclocks for i.MX6 (Lucas Stach) - Add initial power management for i.MX7 (Leonard Crestez) - Add PME_Turn_Off support for i.MX7 (Leonard Crestez) - Fix qcom runtime power management error handling (Bjorn Andersson) - Update TI dra7xx unaligned access errata workaround for host mode as well as endpoint mode (Vignesh R) - Fix kirin section mismatch warning (Nathan Chancellor) * remotes/lorenzo/pci/dwc: PCI: imx: Add PME_Turn_Off support ARM: dts: imx7d: Add turnoff reset dt-bindings: imx6q-pcie: Add turnoff reset for imx7d reset: imx7: Add PCIE_CTRL_APPS_TURNOFF PCI: kirin: Fix section mismatch warning PCI: dwc: pci-dra7xx: Enable errata i870 for both EP and RC mode dt-bindings: PCI: dra7xx: Add bindings for unaligned access in host mode PCI: qcom: Fix error handling in runtime PM support PCI: imx: Initial imx7d pm support PCI: imx6: Support MPLL reconfiguration for 100MHz and 200MHz refclock
2 parents b7c18dc + f4e833b commit 525fde0

File tree

9 files changed

+233
-30
lines changed

9 files changed

+233
-30
lines changed

Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Additional required properties for imx7d-pcie:
5050
- reset-names: Must contain the following entires:
5151
- "pciephy"
5252
- "apps"
53+
- "turnoff"
5354

5455
Example:
5556

Documentation/devicetree/bindings/pci/ti-pci.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ HOST MODE
2626
ranges,
2727
interrupt-map-mask,
2828
interrupt-map : as specified in ../designware-pcie.txt
29+
- ti,syscon-unaligned-access: phandle to the syscon DT node. The 1st argument
30+
should contain the register offset within syscon
31+
and the 2nd argument should contain the bit field
32+
for setting the bit to enable unaligned
33+
access.
2934

3035
DEVICE MODE
3136
===========

arch/arm/boot/dts/imx7d.dtsi

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,9 @@
146146
fsl,max-link-speed = <2>;
147147
power-domains = <&pgc_pcie_phy>;
148148
resets = <&src IMX7_RESET_PCIEPHY>,
149-
<&src IMX7_RESET_PCIE_CTRL_APPS_EN>;
150-
reset-names = "pciephy", "apps";
149+
<&src IMX7_RESET_PCIE_CTRL_APPS_EN>,
150+
<&src IMX7_RESET_PCIE_CTRL_APPS_TURNOFF>;
151+
reset-names = "pciephy", "apps", "turnoff";
151152
status = "disabled";
152153
};
153154
};

drivers/pci/controller/dwc/pci-dra7xx.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ static const struct of_device_id of_dra7xx_pcie_match[] = {
542542
};
543543

544544
/*
545-
* dra7xx_pcie_ep_unaligned_memaccess: workaround for AM572x/AM571x Errata i870
545+
* dra7xx_pcie_unaligned_memaccess: workaround for AM572x/AM571x Errata i870
546546
* @dra7xx: the dra7xx device where the workaround should be applied
547547
*
548548
* Access to the PCIe slave port that are not 32-bit aligned will result
@@ -552,7 +552,7 @@ static const struct of_device_id of_dra7xx_pcie_match[] = {
552552
*
553553
* To avoid this issue set PCIE_SS1_AXI2OCP_LEGACY_MODE_ENABLE to 1.
554554
*/
555-
static int dra7xx_pcie_ep_unaligned_memaccess(struct device *dev)
555+
static int dra7xx_pcie_unaligned_memaccess(struct device *dev)
556556
{
557557
int ret;
558558
struct device_node *np = dev->of_node;
@@ -704,6 +704,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
704704

705705
dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE,
706706
DEVICE_TYPE_RC);
707+
708+
ret = dra7xx_pcie_unaligned_memaccess(dev);
709+
if (ret)
710+
dev_err(dev, "WA for Errata i870 not applied\n");
711+
707712
ret = dra7xx_add_pcie_port(dra7xx, pdev);
708713
if (ret < 0)
709714
goto err_gpio;
@@ -717,7 +722,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
717722
dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE,
718723
DEVICE_TYPE_EP);
719724

720-
ret = dra7xx_pcie_ep_unaligned_memaccess(dev);
725+
ret = dra7xx_pcie_unaligned_memaccess(dev);
721726
if (ret)
722727
goto err_gpio;
723728

drivers/pci/controller/dwc/pci-imx6.c

Lines changed: 171 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct imx6_pcie {
5050
struct regmap *iomuxc_gpr;
5151
struct reset_control *pciephy_reset;
5252
struct reset_control *apps_reset;
53+
struct reset_control *turnoff_reset;
5354
enum imx6_pcie_variants variant;
5455
u32 tx_deemph_gen1;
5556
u32 tx_deemph_gen2_3p5db;
@@ -97,6 +98,16 @@ struct imx6_pcie {
9798
#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
9899

99100
/* PHY registers (not memory-mapped) */
101+
#define PCIE_PHY_ATEOVRD 0x10
102+
#define PCIE_PHY_ATEOVRD_EN (0x1 << 2)
103+
#define PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT 0
104+
#define PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK 0x1
105+
106+
#define PCIE_PHY_MPLL_OVRD_IN_LO 0x11
107+
#define PCIE_PHY_MPLL_MULTIPLIER_SHIFT 2
108+
#define PCIE_PHY_MPLL_MULTIPLIER_MASK 0x7f
109+
#define PCIE_PHY_MPLL_MULTIPLIER_OVRD (0x1 << 9)
110+
100111
#define PCIE_PHY_RX_ASIC_OUT 0x100D
101112
#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
102113

@@ -508,6 +519,50 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
508519
IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
509520
}
510521

522+
static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)
523+
{
524+
unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy);
525+
int mult, div;
526+
u32 val;
527+
528+
switch (phy_rate) {
529+
case 125000000:
530+
/*
531+
* The default settings of the MPLL are for a 125MHz input
532+
* clock, so no need to reconfigure anything in that case.
533+
*/
534+
return 0;
535+
case 100000000:
536+
mult = 25;
537+
div = 0;
538+
break;
539+
case 200000000:
540+
mult = 25;
541+
div = 1;
542+
break;
543+
default:
544+
dev_err(imx6_pcie->pci->dev,
545+
"Unsupported PHY reference clock rate %lu\n", phy_rate);
546+
return -EINVAL;
547+
}
548+
549+
pcie_phy_read(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, &val);
550+
val &= ~(PCIE_PHY_MPLL_MULTIPLIER_MASK <<
551+
PCIE_PHY_MPLL_MULTIPLIER_SHIFT);
552+
val |= mult << PCIE_PHY_MPLL_MULTIPLIER_SHIFT;
553+
val |= PCIE_PHY_MPLL_MULTIPLIER_OVRD;
554+
pcie_phy_write(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, val);
555+
556+
pcie_phy_read(imx6_pcie, PCIE_PHY_ATEOVRD, &val);
557+
val &= ~(PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK <<
558+
PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT);
559+
val |= div << PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT;
560+
val |= PCIE_PHY_ATEOVRD_EN;
561+
pcie_phy_write(imx6_pcie, PCIE_PHY_ATEOVRD, val);
562+
563+
return 0;
564+
}
565+
511566
static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
512567
{
513568
struct dw_pcie *pci = imx6_pcie->pci;
@@ -542,6 +597,24 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
542597
return -EINVAL;
543598
}
544599

600+
static void imx6_pcie_ltssm_enable(struct device *dev)
601+
{
602+
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
603+
604+
switch (imx6_pcie->variant) {
605+
case IMX6Q:
606+
case IMX6SX:
607+
case IMX6QP:
608+
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
609+
IMX6Q_GPR12_PCIE_CTL_2,
610+
IMX6Q_GPR12_PCIE_CTL_2);
611+
break;
612+
case IMX7D:
613+
reset_control_deassert(imx6_pcie->apps_reset);
614+
break;
615+
}
616+
}
617+
545618
static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
546619
{
547620
struct dw_pcie *pci = imx6_pcie->pci;
@@ -560,11 +633,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
560633
dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
561634

562635
/* Start LTSSM. */
563-
if (imx6_pcie->variant == IMX7D)
564-
reset_control_deassert(imx6_pcie->apps_reset);
565-
else
566-
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
567-
IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
636+
imx6_pcie_ltssm_enable(dev);
568637

569638
ret = imx6_pcie_wait_for_link(imx6_pcie);
570639
if (ret)
@@ -632,6 +701,7 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
632701
imx6_pcie_assert_core_reset(imx6_pcie);
633702
imx6_pcie_init_phy(imx6_pcie);
634703
imx6_pcie_deassert_core_reset(imx6_pcie);
704+
imx6_setup_phy_mpll(imx6_pcie);
635705
dw_pcie_setup_rc(pp);
636706
imx6_pcie_establish_link(imx6_pcie);
637707

@@ -682,6 +752,94 @@ static const struct dw_pcie_ops dw_pcie_ops = {
682752
.link_up = imx6_pcie_link_up,
683753
};
684754

755+
#ifdef CONFIG_PM_SLEEP
756+
static void imx6_pcie_ltssm_disable(struct device *dev)
757+
{
758+
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
759+
760+
switch (imx6_pcie->variant) {
761+
case IMX6SX:
762+
case IMX6QP:
763+
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
764+
IMX6Q_GPR12_PCIE_CTL_2, 0);
765+
break;
766+
case IMX7D:
767+
reset_control_assert(imx6_pcie->apps_reset);
768+
break;
769+
default:
770+
dev_err(dev, "ltssm_disable not supported\n");
771+
}
772+
}
773+
774+
static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie)
775+
{
776+
reset_control_assert(imx6_pcie->turnoff_reset);
777+
reset_control_deassert(imx6_pcie->turnoff_reset);
778+
779+
/*
780+
* Components with an upstream port must respond to
781+
* PME_Turn_Off with PME_TO_Ack but we can't check.
782+
*
783+
* The standard recommends a 1-10ms timeout after which to
784+
* proceed anyway as if acks were received.
785+
*/
786+
usleep_range(1000, 10000);
787+
}
788+
789+
static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
790+
{
791+
clk_disable_unprepare(imx6_pcie->pcie);
792+
clk_disable_unprepare(imx6_pcie->pcie_phy);
793+
clk_disable_unprepare(imx6_pcie->pcie_bus);
794+
795+
if (imx6_pcie->variant == IMX7D) {
796+
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
797+
IMX7D_GPR12_PCIE_PHY_REFCLK_SEL,
798+
IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);
799+
}
800+
}
801+
802+
static int imx6_pcie_suspend_noirq(struct device *dev)
803+
{
804+
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
805+
806+
if (imx6_pcie->variant != IMX7D)
807+
return 0;
808+
809+
imx6_pcie_pm_turnoff(imx6_pcie);
810+
imx6_pcie_clk_disable(imx6_pcie);
811+
imx6_pcie_ltssm_disable(dev);
812+
813+
return 0;
814+
}
815+
816+
static int imx6_pcie_resume_noirq(struct device *dev)
817+
{
818+
int ret;
819+
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
820+
struct pcie_port *pp = &imx6_pcie->pci->pp;
821+
822+
if (imx6_pcie->variant != IMX7D)
823+
return 0;
824+
825+
imx6_pcie_assert_core_reset(imx6_pcie);
826+
imx6_pcie_init_phy(imx6_pcie);
827+
imx6_pcie_deassert_core_reset(imx6_pcie);
828+
dw_pcie_setup_rc(pp);
829+
830+
ret = imx6_pcie_establish_link(imx6_pcie);
831+
if (ret < 0)
832+
dev_info(dev, "pcie link is down after resume.\n");
833+
834+
return 0;
835+
}
836+
#endif
837+
838+
static const struct dev_pm_ops imx6_pcie_pm_ops = {
839+
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx6_pcie_suspend_noirq,
840+
imx6_pcie_resume_noirq)
841+
};
842+
685843
static int imx6_pcie_probe(struct platform_device *pdev)
686844
{
687845
struct device *dev = &pdev->dev;
@@ -776,6 +934,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
776934
break;
777935
}
778936

937+
/* Grab turnoff reset */
938+
imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
939+
if (IS_ERR(imx6_pcie->turnoff_reset)) {
940+
dev_err(dev, "Failed to get TURNOFF reset control\n");
941+
return PTR_ERR(imx6_pcie->turnoff_reset);
942+
}
943+
779944
/* Grab GPR config register range */
780945
imx6_pcie->iomuxc_gpr =
781946
syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
@@ -848,6 +1013,7 @@ static struct platform_driver imx6_pcie_driver = {
8481013
.name = "imx6q-pcie",
8491014
.of_match_table = imx6_pcie_of_match,
8501015
.suppress_bind_attrs = true,
1016+
.pm = &imx6_pcie_pm_ops,
8511017
},
8521018
.probe = imx6_pcie_probe,
8531019
.shutdown = imx6_pcie_shutdown,

drivers/pci/controller/dwc/pcie-kirin.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,8 +467,8 @@ static int kirin_pcie_add_msi(struct dw_pcie *pci,
467467
return 0;
468468
}
469469

470-
static int __init kirin_add_pcie_port(struct dw_pcie *pci,
471-
struct platform_device *pdev)
470+
static int kirin_add_pcie_port(struct dw_pcie *pci,
471+
struct platform_device *pdev)
472472
{
473473
int ret;
474474

0 commit comments

Comments
 (0)