|
|
|
|
@ -52,6 +52,8 @@
|
|
|
|
|
#define IMX95_PCIE_REF_CLKEN BIT(23)
|
|
|
|
|
#define IMX95_PCIE_PHY_CR_PARA_SEL BIT(9)
|
|
|
|
|
#define IMX95_PCIE_SS_RW_REG_1 0xf4
|
|
|
|
|
#define IMX95_PCIE_CLKREQ_OVERRIDE_EN BIT(8)
|
|
|
|
|
#define IMX95_PCIE_CLKREQ_OVERRIDE_VAL BIT(9)
|
|
|
|
|
#define IMX95_PCIE_SYS_AUX_PWR_DET BIT(31)
|
|
|
|
|
|
|
|
|
|
#define IMX95_PE0_GEN_CTRL_1 0x1050
|
|
|
|
|
@ -137,6 +139,7 @@ struct imx_pcie_drvdata {
|
|
|
|
|
int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
|
|
|
|
|
int (*core_reset)(struct imx_pcie *pcie, bool assert);
|
|
|
|
|
int (*wait_pll_lock)(struct imx_pcie *pcie);
|
|
|
|
|
void (*clr_clkreq_override)(struct imx_pcie *pcie);
|
|
|
|
|
const struct dw_pcie_host_ops *ops;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -150,6 +153,8 @@ struct imx_pcie {
|
|
|
|
|
struct gpio_desc *reset_gpiod;
|
|
|
|
|
struct clk_bulk_data *clks;
|
|
|
|
|
int num_clks;
|
|
|
|
|
bool supports_clkreq;
|
|
|
|
|
bool enable_ext_refclk;
|
|
|
|
|
struct regmap *iomuxc_gpr;
|
|
|
|
|
u16 msi_ctrl;
|
|
|
|
|
u32 controller_id;
|
|
|
|
|
@ -242,6 +247,8 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie)
|
|
|
|
|
|
|
|
|
|
static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
|
|
|
|
|
{
|
|
|
|
|
bool ext = imx_pcie->enable_ext_refclk;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ERR051624: The Controller Without Vaux Cannot Exit L23 Ready
|
|
|
|
|
* Through Beacon or PERST# De-assertion
|
|
|
|
|
@ -260,13 +267,12 @@ static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
|
|
|
|
|
IMX95_PCIE_PHY_CR_PARA_SEL,
|
|
|
|
|
IMX95_PCIE_PHY_CR_PARA_SEL);
|
|
|
|
|
|
|
|
|
|
regmap_update_bits(imx_pcie->iomuxc_gpr,
|
|
|
|
|
IMX95_PCIE_PHY_GEN_CTRL,
|
|
|
|
|
IMX95_PCIE_REF_USE_PAD, 0);
|
|
|
|
|
regmap_update_bits(imx_pcie->iomuxc_gpr,
|
|
|
|
|
IMX95_PCIE_SS_RW_REG_0,
|
|
|
|
|
regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_PHY_GEN_CTRL,
|
|
|
|
|
ext ? IMX95_PCIE_REF_USE_PAD : 0,
|
|
|
|
|
IMX95_PCIE_REF_USE_PAD);
|
|
|
|
|
regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_0,
|
|
|
|
|
IMX95_PCIE_REF_CLKEN,
|
|
|
|
|
IMX95_PCIE_REF_CLKEN);
|
|
|
|
|
ext ? 0 : IMX95_PCIE_REF_CLKEN);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@ -686,7 +692,7 @@ static int imx6q_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
|
|
|
|
|
static void imx8mm_pcie_clkreq_override(struct imx_pcie *imx_pcie, bool enable)
|
|
|
|
|
{
|
|
|
|
|
int offset = imx_pcie_grp_offset(imx_pcie);
|
|
|
|
|
|
|
|
|
|
@ -696,6 +702,11 @@ static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
|
|
|
|
|
regmap_update_bits(imx_pcie->iomuxc_gpr, offset,
|
|
|
|
|
IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN,
|
|
|
|
|
enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
|
|
|
|
|
{
|
|
|
|
|
imx8mm_pcie_clkreq_override(imx_pcie, enable);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -707,6 +718,32 @@ static int imx7d_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void imx95_pcie_clkreq_override(struct imx_pcie *imx_pcie, bool enable)
|
|
|
|
|
{
|
|
|
|
|
regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
|
|
|
|
|
IMX95_PCIE_CLKREQ_OVERRIDE_EN,
|
|
|
|
|
enable ? IMX95_PCIE_CLKREQ_OVERRIDE_EN : 0);
|
|
|
|
|
regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
|
|
|
|
|
IMX95_PCIE_CLKREQ_OVERRIDE_VAL,
|
|
|
|
|
enable ? IMX95_PCIE_CLKREQ_OVERRIDE_VAL : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int imx95_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
|
|
|
|
|
{
|
|
|
|
|
imx95_pcie_clkreq_override(imx_pcie, enable);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie)
|
|
|
|
|
{
|
|
|
|
|
imx8mm_pcie_clkreq_override(imx_pcie, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void imx95_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie)
|
|
|
|
|
{
|
|
|
|
|
imx95_pcie_clkreq_override(imx_pcie, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int imx_pcie_clk_enable(struct imx_pcie *imx_pcie)
|
|
|
|
|
{
|
|
|
|
|
struct dw_pcie *pci = imx_pcie->pci;
|
|
|
|
|
@ -1323,6 +1360,12 @@ static void imx_pcie_host_post_init(struct dw_pcie_rp *pp)
|
|
|
|
|
dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
|
|
|
|
|
dw_pcie_dbi_ro_wr_dis(pci);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Clear CLKREQ# override if supports_clkreq is true and link is up */
|
|
|
|
|
if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) {
|
|
|
|
|
if (imx_pcie->drvdata->clr_clkreq_override)
|
|
|
|
|
imx_pcie->drvdata->clr_clkreq_override(imx_pcie);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@ -1606,7 +1649,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
|
|
|
|
|
struct imx_pcie *imx_pcie;
|
|
|
|
|
struct device_node *np;
|
|
|
|
|
struct device_node *node = dev->of_node;
|
|
|
|
|
int ret, domain;
|
|
|
|
|
int i, ret, domain;
|
|
|
|
|
u16 val;
|
|
|
|
|
|
|
|
|
|
imx_pcie = devm_kzalloc(dev, sizeof(*imx_pcie), GFP_KERNEL);
|
|
|
|
|
@ -1657,6 +1700,9 @@ static int imx_pcie_probe(struct platform_device *pdev)
|
|
|
|
|
if (imx_pcie->num_clks < 0)
|
|
|
|
|
return dev_err_probe(dev, imx_pcie->num_clks,
|
|
|
|
|
"failed to get clocks\n");
|
|
|
|
|
for (i = 0; i < imx_pcie->num_clks; i++)
|
|
|
|
|
if (strncmp(imx_pcie->clks[i].id, "extref", 6) == 0)
|
|
|
|
|
imx_pcie->enable_ext_refclk = true;
|
|
|
|
|
|
|
|
|
|
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_PHYDRV)) {
|
|
|
|
|
imx_pcie->phy = devm_phy_get(dev, "pcie-phy");
|
|
|
|
|
@ -1744,6 +1790,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
|
|
|
|
|
/* Limit link speed */
|
|
|
|
|
pci->max_link_speed = 1;
|
|
|
|
|
of_property_read_u32(node, "fsl,max-link-speed", &pci->max_link_speed);
|
|
|
|
|
imx_pcie->supports_clkreq = of_property_read_bool(node, "supports-clkreq");
|
|
|
|
|
|
|
|
|
|
ret = devm_regulator_get_enable_optional(&pdev->dev, "vpcie3v3aux");
|
|
|
|
|
if (ret < 0 && ret != -ENODEV)
|
|
|
|
|
@ -1881,6 +1928,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
|
|
|
|
.mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE,
|
|
|
|
|
.init_phy = imx8mq_pcie_init_phy,
|
|
|
|
|
.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
|
|
|
|
|
.clr_clkreq_override = imx8mm_pcie_clr_clkreq_override,
|
|
|
|
|
},
|
|
|
|
|
[IMX8MM] = {
|
|
|
|
|
.variant = IMX8MM,
|
|
|
|
|
@ -1891,6 +1939,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
|
|
|
|
.mode_off[0] = IOMUXC_GPR12,
|
|
|
|
|
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
|
|
|
|
|
.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
|
|
|
|
|
.clr_clkreq_override = imx8mm_pcie_clr_clkreq_override,
|
|
|
|
|
},
|
|
|
|
|
[IMX8MP] = {
|
|
|
|
|
.variant = IMX8MP,
|
|
|
|
|
@ -1901,6 +1950,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
|
|
|
|
.mode_off[0] = IOMUXC_GPR12,
|
|
|
|
|
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
|
|
|
|
|
.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
|
|
|
|
|
.clr_clkreq_override = imx8mm_pcie_clr_clkreq_override,
|
|
|
|
|
},
|
|
|
|
|
[IMX8Q] = {
|
|
|
|
|
.variant = IMX8Q,
|
|
|
|
|
@ -1921,6 +1971,8 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
|
|
|
|
.core_reset = imx95_pcie_core_reset,
|
|
|
|
|
.init_phy = imx95_pcie_init_phy,
|
|
|
|
|
.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
|
|
|
|
|
.enable_ref_clk = imx95_pcie_enable_ref_clk,
|
|
|
|
|
.clr_clkreq_override = imx95_pcie_clr_clkreq_override,
|
|
|
|
|
},
|
|
|
|
|
[IMX8MQ_EP] = {
|
|
|
|
|
.variant = IMX8MQ_EP,
|
|
|
|
|
@ -1977,6 +2029,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
|
|
|
|
.core_reset = imx95_pcie_core_reset,
|
|
|
|
|
.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
|
|
|
|
|
.epc_features = &imx95_pcie_epc_features,
|
|
|
|
|
.enable_ref_clk = imx95_pcie_enable_ref_clk,
|
|
|
|
|
.mode = DW_PCIE_EP_TYPE,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|