On Fri, Mar 28, 2025 at 11:02:13AM +0800, Richard Zhu wrote: > The look up table(LUT) setting would be lost during PCIe suspend on i.MX95. > > To ensure proper functionality after resume, save and restore the LUT > setting in suspend and resume operations. > > Signed-off-by: Richard Zhu <hongxing.zhu@xxxxxxx> Reviewed-by: Frank Li <Frank.Li@xxxxxxx> > --- > drivers/pci/controller/dwc/pci-imx6.c | 47 +++++++++++++++++++++++++++ > 1 file changed, 47 insertions(+) > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c > index 40eeb02ffb5d..d8f4608eb7da 100644 > --- a/drivers/pci/controller/dwc/pci-imx6.c > +++ b/drivers/pci/controller/dwc/pci-imx6.c > @@ -138,6 +138,11 @@ struct imx_pcie_drvdata { > const struct dw_pcie_host_ops *ops; > }; > > +struct imx_lut_data { > + u32 data1; > + u32 data2; > +}; > + > struct imx_pcie { > struct dw_pcie *pci; > struct gpio_desc *reset_gpiod; > @@ -157,6 +162,8 @@ struct imx_pcie { > struct regulator *vph; > void __iomem *phy_base; > > + /* LUT data for pcie */ > + struct imx_lut_data luts[IMX95_MAX_LUT]; > /* power domain for pcie */ > struct device *pd_pcie; > /* power domain for pcie phy */ > @@ -1505,6 +1512,42 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save) > } > } > > +static void imx_pcie_lut_save(struct imx_pcie *imx_pcie) > +{ > + u32 data1, data2; > + int i; > + > + for (i = 0; i < IMX95_MAX_LUT; i++) { > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, > + IMX95_PEO_LUT_RWA | i); > + regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, &data1); > + regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, &data2); > + if (data1 & IMX95_PE0_LUT_VLD) { > + imx_pcie->luts[i].data1 = data1; > + imx_pcie->luts[i].data2 = data2; > + } else { > + imx_pcie->luts[i].data1 = 0; > + imx_pcie->luts[i].data2 = 0; > + } > + } > +} > + > +static void imx_pcie_lut_restore(struct imx_pcie *imx_pcie) > +{ > + int i; > + > + for (i = 0; i < IMX95_MAX_LUT; i++) { > + if ((imx_pcie->luts[i].data1 & IMX95_PE0_LUT_VLD) == 0) > + continue; > + > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, > + imx_pcie->luts[i].data1); > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, > + imx_pcie->luts[i].data2); > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i); > + } > +} > + > static int imx_pcie_suspend_noirq(struct device *dev) > { > struct imx_pcie *imx_pcie = dev_get_drvdata(dev); > @@ -1513,6 +1556,8 @@ static int imx_pcie_suspend_noirq(struct device *dev) > return 0; > > imx_pcie_msi_save_restore(imx_pcie, true); > + if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT)) > + imx_pcie_lut_save(imx_pcie); > if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) { > /* > * The minimum for a workaround would be to set PERST# and to > @@ -1557,6 +1602,8 @@ static int imx_pcie_resume_noirq(struct device *dev) > if (ret) > return ret; > } > + if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT)) > + imx_pcie_lut_restore(imx_pcie); > imx_pcie_msi_save_restore(imx_pcie, false); > > return 0; > -- > 2.37.1 >