Skip to content

Commit 62dea87

Browse files
committed
Merge branch 'pci/controller/dwc-imx6'
- Add DT binding and driver support for an optional external refclock in addition to the refclock from the internal PLL (Richard Zhu) - Apply i.MX95 ERR051586 erratum workaround (release CLKREQ# so endpoint can assert it when required) during resume (Richard Zhu) - Enable i.MX95 REFCLK by overriding CLKREQ# so it's driven by default (Richard Zhu) - Clear CLKREQ# override if link is up and DT says 'supports-clkreq' so endpoints can use CLKREQ# to exit the L1.2 state (Richard Zhu) * pci/controller/dwc-imx6: PCI: imx6: Clear CLKREQ# override if 'supports-clkreq' DT property is available PCI: imx6: Add CLKREQ# override to enable REFCLK for i.MX95 PCIe PCI: dwc: Invoke post_init in dw_pcie_resume_noirq() PCI: imx6: Add external reference clock input mode support dt-bindings: PCI: pci-imx6: Add external reference clock input dt-bindings: PCI: dwc: Add external reference clock input
2 parents 93c398b + a152a90 commit 62dea87

4 files changed

Lines changed: 75 additions & 10 deletions

File tree

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ properties:
4444

4545
clock-names:
4646
minItems: 3
47-
maxItems: 5
47+
maxItems: 6
4848

4949
interrupts:
5050
minItems: 1
@@ -212,14 +212,17 @@ allOf:
212212
then:
213213
properties:
214214
clocks:
215-
maxItems: 5
215+
minItems: 5
216+
maxItems: 6
216217
clock-names:
218+
minItems: 5
217219
items:
218220
- const: pcie
219221
- const: pcie_bus
220222
- const: pcie_phy
221223
- const: pcie_aux
222224
- const: ref
225+
- const: extref # Optional
223226

224227
unevaluatedProperties: false
225228

Documentation/devicetree/bindings/pci/snps,dw-pcie-common.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ properties:
105105
define it with this name (for instance pipe, core and aux can
106106
be connected to a single source of the periodic signal).
107107
const: ref
108+
- description:
109+
Some dwc wrappers (like i.MX95 PCIes) have two reference clock
110+
inputs, one from an internal PLL, the other from an off-chip crystal
111+
oscillator. If present, 'extref' refers to a reference clock from
112+
an external oscillator.
113+
const: extref
108114
- description:
109115
Clock for the PHY registers interface. Originally this is
110116
a PHY-viewport-based interface, but some platform may have

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

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
#define IMX95_PCIE_REF_CLKEN BIT(23)
5353
#define IMX95_PCIE_PHY_CR_PARA_SEL BIT(9)
5454
#define IMX95_PCIE_SS_RW_REG_1 0xf4
55+
#define IMX95_PCIE_CLKREQ_OVERRIDE_EN BIT(8)
56+
#define IMX95_PCIE_CLKREQ_OVERRIDE_VAL BIT(9)
5557
#define IMX95_PCIE_SYS_AUX_PWR_DET BIT(31)
5658

5759
#define IMX95_PE0_GEN_CTRL_1 0x1050
@@ -137,6 +139,7 @@ struct imx_pcie_drvdata {
137139
int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
138140
int (*core_reset)(struct imx_pcie *pcie, bool assert);
139141
int (*wait_pll_lock)(struct imx_pcie *pcie);
142+
void (*clr_clkreq_override)(struct imx_pcie *pcie);
140143
const struct dw_pcie_host_ops *ops;
141144
};
142145

@@ -150,6 +153,8 @@ struct imx_pcie {
150153
struct gpio_desc *reset_gpiod;
151154
struct clk_bulk_data *clks;
152155
int num_clks;
156+
bool supports_clkreq;
157+
bool enable_ext_refclk;
153158
struct regmap *iomuxc_gpr;
154159
u16 msi_ctrl;
155160
u32 controller_id;
@@ -242,6 +247,8 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie)
242247

243248
static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
244249
{
250+
bool ext = imx_pcie->enable_ext_refclk;
251+
245252
/*
246253
* ERR051624: The Controller Without Vaux Cannot Exit L23 Ready
247254
* Through Beacon or PERST# De-assertion
@@ -260,13 +267,12 @@ static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
260267
IMX95_PCIE_PHY_CR_PARA_SEL,
261268
IMX95_PCIE_PHY_CR_PARA_SEL);
262269

263-
regmap_update_bits(imx_pcie->iomuxc_gpr,
264-
IMX95_PCIE_PHY_GEN_CTRL,
265-
IMX95_PCIE_REF_USE_PAD, 0);
266-
regmap_update_bits(imx_pcie->iomuxc_gpr,
267-
IMX95_PCIE_SS_RW_REG_0,
270+
regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_PHY_GEN_CTRL,
271+
ext ? IMX95_PCIE_REF_USE_PAD : 0,
272+
IMX95_PCIE_REF_USE_PAD);
273+
regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_0,
268274
IMX95_PCIE_REF_CLKEN,
269-
IMX95_PCIE_REF_CLKEN);
275+
ext ? 0 : IMX95_PCIE_REF_CLKEN);
270276

271277
return 0;
272278
}
@@ -686,7 +692,7 @@ static int imx6q_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
686692
return 0;
687693
}
688694

689-
static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
695+
static void imx8mm_pcie_clkreq_override(struct imx_pcie *imx_pcie, bool enable)
690696
{
691697
int offset = imx_pcie_grp_offset(imx_pcie);
692698

@@ -696,6 +702,11 @@ static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
696702
regmap_update_bits(imx_pcie->iomuxc_gpr, offset,
697703
IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN,
698704
enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0);
705+
}
706+
707+
static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
708+
{
709+
imx8mm_pcie_clkreq_override(imx_pcie, enable);
699710
return 0;
700711
}
701712

@@ -707,6 +718,32 @@ static int imx7d_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
707718
return 0;
708719
}
709720

721+
static void imx95_pcie_clkreq_override(struct imx_pcie *imx_pcie, bool enable)
722+
{
723+
regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
724+
IMX95_PCIE_CLKREQ_OVERRIDE_EN,
725+
enable ? IMX95_PCIE_CLKREQ_OVERRIDE_EN : 0);
726+
regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
727+
IMX95_PCIE_CLKREQ_OVERRIDE_VAL,
728+
enable ? IMX95_PCIE_CLKREQ_OVERRIDE_VAL : 0);
729+
}
730+
731+
static int imx95_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
732+
{
733+
imx95_pcie_clkreq_override(imx_pcie, enable);
734+
return 0;
735+
}
736+
737+
static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie)
738+
{
739+
imx8mm_pcie_clkreq_override(imx_pcie, false);
740+
}
741+
742+
static void imx95_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie)
743+
{
744+
imx95_pcie_clkreq_override(imx_pcie, false);
745+
}
746+
710747
static int imx_pcie_clk_enable(struct imx_pcie *imx_pcie)
711748
{
712749
struct dw_pcie *pci = imx_pcie->pci;
@@ -1323,6 +1360,12 @@ static void imx_pcie_host_post_init(struct dw_pcie_rp *pp)
13231360
dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
13241361
dw_pcie_dbi_ro_wr_dis(pci);
13251362
}
1363+
1364+
/* Clear CLKREQ# override if supports_clkreq is true and link is up */
1365+
if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) {
1366+
if (imx_pcie->drvdata->clr_clkreq_override)
1367+
imx_pcie->drvdata->clr_clkreq_override(imx_pcie);
1368+
}
13261369
}
13271370

13281371
/*
@@ -1606,7 +1649,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
16061649
struct imx_pcie *imx_pcie;
16071650
struct device_node *np;
16081651
struct device_node *node = dev->of_node;
1609-
int ret, domain;
1652+
int i, ret, domain;
16101653
u16 val;
16111654

16121655
imx_pcie = devm_kzalloc(dev, sizeof(*imx_pcie), GFP_KERNEL);
@@ -1657,6 +1700,9 @@ static int imx_pcie_probe(struct platform_device *pdev)
16571700
if (imx_pcie->num_clks < 0)
16581701
return dev_err_probe(dev, imx_pcie->num_clks,
16591702
"failed to get clocks\n");
1703+
for (i = 0; i < imx_pcie->num_clks; i++)
1704+
if (strncmp(imx_pcie->clks[i].id, "extref", 6) == 0)
1705+
imx_pcie->enable_ext_refclk = true;
16601706

16611707
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_PHYDRV)) {
16621708
imx_pcie->phy = devm_phy_get(dev, "pcie-phy");
@@ -1744,6 +1790,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
17441790
/* Limit link speed */
17451791
pci->max_link_speed = 1;
17461792
of_property_read_u32(node, "fsl,max-link-speed", &pci->max_link_speed);
1793+
imx_pcie->supports_clkreq = of_property_read_bool(node, "supports-clkreq");
17471794

17481795
ret = devm_regulator_get_enable_optional(&pdev->dev, "vpcie3v3aux");
17491796
if (ret < 0 && ret != -ENODEV)
@@ -1881,6 +1928,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
18811928
.mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE,
18821929
.init_phy = imx8mq_pcie_init_phy,
18831930
.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
1931+
.clr_clkreq_override = imx8mm_pcie_clr_clkreq_override,
18841932
},
18851933
[IMX8MM] = {
18861934
.variant = IMX8MM,
@@ -1891,6 +1939,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
18911939
.mode_off[0] = IOMUXC_GPR12,
18921940
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
18931941
.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
1942+
.clr_clkreq_override = imx8mm_pcie_clr_clkreq_override,
18941943
},
18951944
[IMX8MP] = {
18961945
.variant = IMX8MP,
@@ -1901,6 +1950,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
19011950
.mode_off[0] = IOMUXC_GPR12,
19021951
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
19031952
.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
1953+
.clr_clkreq_override = imx8mm_pcie_clr_clkreq_override,
19041954
},
19051955
[IMX8Q] = {
19061956
.variant = IMX8Q,
@@ -1921,6 +1971,8 @@ static const struct imx_pcie_drvdata drvdata[] = {
19211971
.core_reset = imx95_pcie_core_reset,
19221972
.init_phy = imx95_pcie_init_phy,
19231973
.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
1974+
.enable_ref_clk = imx95_pcie_enable_ref_clk,
1975+
.clr_clkreq_override = imx95_pcie_clr_clkreq_override,
19241976
},
19251977
[IMX8MQ_EP] = {
19261978
.variant = IMX8MQ_EP,
@@ -1977,6 +2029,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
19772029
.core_reset = imx95_pcie_core_reset,
19782030
.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
19792031
.epc_features = &imx95_pcie_epc_features,
2032+
.enable_ref_clk = imx95_pcie_enable_ref_clk,
19802033
.mode = DW_PCIE_EP_TYPE,
19812034
},
19822035
};

drivers/pci/controller/dwc/pcie-designware-host.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,9 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
13171317
if (ret)
13181318
return ret;
13191319

1320+
if (pci->pp.ops->post_init)
1321+
pci->pp.ops->post_init(&pci->pp);
1322+
13201323
return ret;
13211324
}
13221325
EXPORT_SYMBOL_GPL(dw_pcie_resume_noirq);

0 commit comments

Comments
 (0)