diff options
Diffstat (limited to 'drivers/pci/controller/dwc')
| -rw-r--r-- | drivers/pci/controller/dwc/pci-imx6.c | 630 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pci-keystone.c | 12 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pci-layerscape-ep.c | 5 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-ep.c | 7 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-host.c | 21 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-keembay.c | 8 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom.c | 42 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-rcar-gen4.c | 4 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-tegra194.c | 10 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-uniphier-ep.c | 15 | 
10 files changed, 451 insertions, 303 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index dc2c036ab28c..99a60270b26c 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -42,6 +42,19 @@  #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11, 8)  #define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000 +#define IMX95_PCIE_PHY_GEN_CTRL			0x0 +#define IMX95_PCIE_REF_USE_PAD			BIT(17) + +#define IMX95_PCIE_SS_RW_REG_0			0xf0 +#define IMX95_PCIE_REF_CLKEN			BIT(23) +#define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9) + +#define IMX95_PE0_GEN_CTRL_1			0x1050 +#define IMX95_PCIE_DEVICE_TYPE			GENMASK(3, 0) + +#define IMX95_PE0_GEN_CTRL_3			0x1058 +#define IMX95_PCIE_LTSSM_EN			BIT(0) +  #define to_imx6_pcie(x)	dev_get_drvdata((x)->dev)  enum imx6_pcie_variants { @@ -52,14 +65,29 @@ enum imx6_pcie_variants {  	IMX8MQ,  	IMX8MM,  	IMX8MP, +	IMX95,  	IMX8MQ_EP,  	IMX8MM_EP,  	IMX8MP_EP, +	IMX95_EP,  };  #define IMX6_PCIE_FLAG_IMX6_PHY			BIT(0)  #define IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE	BIT(1)  #define IMX6_PCIE_FLAG_SUPPORTS_SUSPEND		BIT(2) +#define IMX6_PCIE_FLAG_HAS_PHYDRV			BIT(3) +#define IMX6_PCIE_FLAG_HAS_APP_RESET		BIT(4) +#define IMX6_PCIE_FLAG_HAS_PHY_RESET		BIT(5) +#define IMX6_PCIE_FLAG_HAS_SERDES		BIT(6) +#define IMX6_PCIE_FLAG_SUPPORT_64BIT		BIT(7) + +#define imx6_check_flag(pci, val)     (pci->drvdata->flags & val) + +#define IMX6_PCIE_MAX_CLKS       6 + +#define IMX6_PCIE_MAX_INSTANCES			2 + +struct imx6_pcie;  struct imx6_pcie_drvdata {  	enum imx6_pcie_variants variant; @@ -67,6 +95,14 @@ struct imx6_pcie_drvdata {  	u32 flags;  	int dbi_length;  	const char *gpr; +	const char * const *clk_names; +	const u32 clks_cnt; +	const u32 ltssm_off; +	const u32 ltssm_mask; +	const u32 mode_off[IMX6_PCIE_MAX_INSTANCES]; +	const u32 mode_mask[IMX6_PCIE_MAX_INSTANCES]; +	const struct pci_epc_features *epc_features; +	int (*init_phy)(struct imx6_pcie *pcie);  };  struct imx6_pcie { @@ -74,11 +110,7 @@ struct imx6_pcie {  	int			reset_gpio;  	bool			gpio_active_high;  	bool			link_is_up; -	struct clk		*pcie_bus; -	struct clk		*pcie_phy; -	struct clk		*pcie_inbound_axi; -	struct clk		*pcie; -	struct clk		*pcie_aux; +	struct clk_bulk_data	clks[IMX6_PCIE_MAX_CLKS];  	struct regmap		*iomuxc_gpr;  	u16			msi_ctrl;  	u32			controller_id; @@ -165,34 +197,44 @@ static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)  	return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14;  } +static int imx95_pcie_init_phy(struct imx6_pcie *imx6_pcie) +{ +	regmap_update_bits(imx6_pcie->iomuxc_gpr, +			IMX95_PCIE_SS_RW_REG_0, +			IMX95_PCIE_PHY_CR_PARA_SEL, +			IMX95_PCIE_PHY_CR_PARA_SEL); + +	regmap_update_bits(imx6_pcie->iomuxc_gpr, +			   IMX95_PCIE_PHY_GEN_CTRL, +			   IMX95_PCIE_REF_USE_PAD, 0); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, +			   IMX95_PCIE_SS_RW_REG_0, +			   IMX95_PCIE_REF_CLKEN, +			   IMX95_PCIE_REF_CLKEN); + +	return 0; +} +  static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)  { -	unsigned int mask, val, mode; +	const struct imx6_pcie_drvdata *drvdata = imx6_pcie->drvdata; +	unsigned int mask, val, mode, id; -	if (imx6_pcie->drvdata->mode == DW_PCIE_EP_TYPE) +	if (drvdata->mode == DW_PCIE_EP_TYPE)  		mode = PCI_EXP_TYPE_ENDPOINT;  	else  		mode = PCI_EXP_TYPE_ROOT_PORT; -	switch (imx6_pcie->drvdata->variant) { -	case IMX8MQ: -	case IMX8MQ_EP: -		if (imx6_pcie->controller_id == 1) { -			mask = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE; -			val  = FIELD_PREP(IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, -					  mode); -		} else { -			mask = IMX6Q_GPR12_DEVICE_TYPE; -			val  = FIELD_PREP(IMX6Q_GPR12_DEVICE_TYPE, mode); -		} -		break; -	default: -		mask = IMX6Q_GPR12_DEVICE_TYPE; -		val  = FIELD_PREP(IMX6Q_GPR12_DEVICE_TYPE, mode); -		break; -	} +	id = imx6_pcie->controller_id; + +	/* If mode_mask[id] is zero, means each controller have its individual gpr */ +	if (!drvdata->mode_mask[id]) +		id = 0; + +	mask = drvdata->mode_mask[id]; +	val = mode << (ffs(mask) - 1); -	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, mask, val); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, drvdata->mode_off[id], mask, val);  }  static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, bool exp_val) @@ -320,76 +362,66 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, u16 data)  	return 0;  } -static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) +static int imx8mq_pcie_init_phy(struct imx6_pcie *imx6_pcie)  { -	switch (imx6_pcie->drvdata->variant) { -	case IMX8MM: -	case IMX8MM_EP: -	case IMX8MP: -	case IMX8MP_EP: -		/* -		 * The PHY initialization had been done in the PHY -		 * driver, break here directly. -		 */ -		break; -	case IMX8MQ: -	case IMX8MQ_EP: -		/* -		 * TODO: Currently this code assumes external -		 * oscillator is being used -		 */ +	/* TODO: Currently this code assumes external oscillator is being used */ +	regmap_update_bits(imx6_pcie->iomuxc_gpr, +			   imx6_pcie_grp_offset(imx6_pcie), +			   IMX8MQ_GPR_PCIE_REF_USE_PAD, +			   IMX8MQ_GPR_PCIE_REF_USE_PAD); +	/* +	 * Regarding the datasheet, the PCIE_VPH is suggested to be 1.8V. If the PCIE_VPH is +	 * supplied by 3.3V, the VREG_BYPASS should be cleared to zero. +	 */ +	if (imx6_pcie->vph && regulator_get_voltage(imx6_pcie->vph) > 3000000)  		regmap_update_bits(imx6_pcie->iomuxc_gpr,  				   imx6_pcie_grp_offset(imx6_pcie), -				   IMX8MQ_GPR_PCIE_REF_USE_PAD, -				   IMX8MQ_GPR_PCIE_REF_USE_PAD); -		/* -		 * Regarding the datasheet, the PCIE_VPH is suggested -		 * to be 1.8V. If the PCIE_VPH is supplied by 3.3V, the -		 * VREG_BYPASS should be cleared to zero. -		 */ -		if (imx6_pcie->vph && -		    regulator_get_voltage(imx6_pcie->vph) > 3000000) -			regmap_update_bits(imx6_pcie->iomuxc_gpr, -					   imx6_pcie_grp_offset(imx6_pcie), -					   IMX8MQ_GPR_PCIE_VREG_BYPASS, -					   0); -		break; -	case IMX7D: -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, -				   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0); -		break; -	case IMX6SX: -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, -				   IMX6SX_GPR12_PCIE_RX_EQ_MASK, -				   IMX6SX_GPR12_PCIE_RX_EQ_2); -		fallthrough; -	default: -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, +				   IMX8MQ_GPR_PCIE_VREG_BYPASS, +				   0); + +	return 0; +} + +static int imx7d_pcie_init_phy(struct imx6_pcie *imx6_pcie) +{ +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0); + +	return 0; +} + +static int imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) +{ +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,  				   IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); -		/* configure constant input signal to the pcie ctrl and phy */ -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, -				   IMX6Q_GPR12_LOS_LEVEL, 9 << 4); - -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, -				   IMX6Q_GPR8_TX_DEEMPH_GEN1, -				   imx6_pcie->tx_deemph_gen1 << 0); -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, -				   IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, -				   imx6_pcie->tx_deemph_gen2_3p5db << 6); -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, -				   IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, -				   imx6_pcie->tx_deemph_gen2_6db << 12); -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, -				   IMX6Q_GPR8_TX_SWING_FULL, -				   imx6_pcie->tx_swing_full << 18); -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, -				   IMX6Q_GPR8_TX_SWING_LOW, -				   imx6_pcie->tx_swing_low << 25); -		break; -	} +	/* configure constant input signal to the pcie ctrl and phy */ +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, +			   IMX6Q_GPR12_LOS_LEVEL, 9 << 4); + +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			   IMX6Q_GPR8_TX_DEEMPH_GEN1, +			   imx6_pcie->tx_deemph_gen1 << 0); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			   IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, +			   imx6_pcie->tx_deemph_gen2_3p5db << 6); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			   IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, +			   imx6_pcie->tx_deemph_gen2_6db << 12); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			   IMX6Q_GPR8_TX_SWING_FULL, +			   imx6_pcie->tx_swing_full << 18); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			   IMX6Q_GPR8_TX_SWING_LOW, +			   imx6_pcie->tx_swing_low << 25); +	return 0; +} -	imx6_pcie_configure_type(imx6_pcie); +static int imx6sx_pcie_init_phy(struct imx6_pcie *imx6_pcie) +{ +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, +			   IMX6SX_GPR12_PCIE_RX_EQ_MASK, IMX6SX_GPR12_PCIE_RX_EQ_2); + +	return imx6_pcie_init_phy(imx6_pcie);  }  static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie) @@ -407,13 +439,18 @@ static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)  static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)  { -	unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy); +	unsigned long phy_rate = 0;  	int mult, div;  	u16 val; +	int i;  	if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY))  		return 0; +	for (i = 0; i < imx6_pcie->drvdata->clks_cnt; i++) +		if (strncmp(imx6_pcie->clks[i].id, "pcie_phy", 8) == 0) +			phy_rate = clk_get_rate(imx6_pcie->clks[i].clk); +  	switch (phy_rate) {  	case 125000000:  		/* @@ -550,19 +587,11 @@ static int imx6_pcie_attach_pd(struct device *dev)  static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)  { -	struct dw_pcie *pci = imx6_pcie->pci; -	struct device *dev = pci->dev;  	unsigned int offset;  	int ret = 0;  	switch (imx6_pcie->drvdata->variant) {  	case IMX6SX: -		ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi); -		if (ret) { -			dev_err(dev, "unable to enable pcie_axi clock\n"); -			break; -		} -  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,  				   IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0);  		break; @@ -582,6 +611,8 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)  				   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);  		break;  	case IMX7D: +	case IMX95: +	case IMX95_EP:  		break;  	case IMX8MM:  	case IMX8MM_EP: @@ -589,12 +620,6 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)  	case IMX8MQ_EP:  	case IMX8MP:  	case IMX8MP_EP: -		ret = clk_prepare_enable(imx6_pcie->pcie_aux); -		if (ret) { -			dev_err(dev, "unable to enable pcie_aux clock\n"); -			break; -		} -  		offset = imx6_pcie_grp_offset(imx6_pcie);  		/*  		 * Set the over ride low and enabled @@ -615,9 +640,6 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)  static void imx6_pcie_disable_ref_clk(struct imx6_pcie *imx6_pcie)  {  	switch (imx6_pcie->drvdata->variant) { -	case IMX6SX: -		clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); -		break;  	case IMX6QP:  	case IMX6Q:  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, @@ -631,14 +653,6 @@ static void imx6_pcie_disable_ref_clk(struct imx6_pcie *imx6_pcie)  				   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL,  				   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);  		break; -	case IMX8MM: -	case IMX8MM_EP: -	case IMX8MQ: -	case IMX8MQ_EP: -	case IMX8MP: -	case IMX8MP_EP: -		clk_disable_unprepare(imx6_pcie->pcie_aux); -		break;  	default:  		break;  	} @@ -650,23 +664,9 @@ static int imx6_pcie_clk_enable(struct imx6_pcie *imx6_pcie)  	struct device *dev = pci->dev;  	int ret; -	ret = clk_prepare_enable(imx6_pcie->pcie_phy); -	if (ret) { -		dev_err(dev, "unable to enable pcie_phy clock\n"); +	ret = clk_bulk_prepare_enable(imx6_pcie->drvdata->clks_cnt, imx6_pcie->clks); +	if (ret)  		return ret; -	} - -	ret = clk_prepare_enable(imx6_pcie->pcie_bus); -	if (ret) { -		dev_err(dev, "unable to enable pcie_bus clock\n"); -		goto err_pcie_bus; -	} - -	ret = clk_prepare_enable(imx6_pcie->pcie); -	if (ret) { -		dev_err(dev, "unable to enable pcie clock\n"); -		goto err_pcie; -	}  	ret = imx6_pcie_enable_ref_clk(imx6_pcie);  	if (ret) { @@ -679,11 +679,7 @@ static int imx6_pcie_clk_enable(struct imx6_pcie *imx6_pcie)  	return 0;  err_ref_clk: -	clk_disable_unprepare(imx6_pcie->pcie); -err_pcie: -	clk_disable_unprepare(imx6_pcie->pcie_bus); -err_pcie_bus: -	clk_disable_unprepare(imx6_pcie->pcie_phy); +	clk_bulk_disable_unprepare(imx6_pcie->drvdata->clks_cnt, imx6_pcie->clks);  	return ret;  } @@ -691,25 +687,15 @@ err_pcie_bus:  static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)  {  	imx6_pcie_disable_ref_clk(imx6_pcie); -	clk_disable_unprepare(imx6_pcie->pcie); -	clk_disable_unprepare(imx6_pcie->pcie_bus); -	clk_disable_unprepare(imx6_pcie->pcie_phy); +	clk_bulk_disable_unprepare(imx6_pcie->drvdata->clks_cnt, imx6_pcie->clks);  }  static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)  { +	reset_control_assert(imx6_pcie->pciephy_reset); +	reset_control_assert(imx6_pcie->apps_reset); +  	switch (imx6_pcie->drvdata->variant) { -	case IMX7D: -	case IMX8MQ: -	case IMX8MQ_EP: -		reset_control_assert(imx6_pcie->pciephy_reset); -		fallthrough; -	case IMX8MM: -	case IMX8MM_EP: -	case IMX8MP: -	case IMX8MP_EP: -		reset_control_assert(imx6_pcie->apps_reset); -		break;  	case IMX6SX:  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,  				   IMX6SX_GPR12_PCIE_TEST_POWERDOWN, @@ -730,6 +716,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,  				   IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);  		break; +	default: +		break;  	}  	/* Some boards don't have PCIe reset GPIO. */ @@ -743,14 +731,10 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)  	struct dw_pcie *pci = imx6_pcie->pci;  	struct device *dev = pci->dev; +	reset_control_deassert(imx6_pcie->pciephy_reset); +  	switch (imx6_pcie->drvdata->variant) { -	case IMX8MQ: -	case IMX8MQ_EP: -		reset_control_deassert(imx6_pcie->pciephy_reset); -		break;  	case IMX7D: -		reset_control_deassert(imx6_pcie->pciephy_reset); -  		/* Workaround for ERR010728, failure of PCI-e PLL VCO to  		 * oscillate, especially when cold.  This turns off "Duty-cycle  		 * Corrector" and other mysterious undocumented things. @@ -782,11 +766,7 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)  		usleep_range(200, 500);  		break; -	case IMX6Q:		/* Nothing to do */ -	case IMX8MM: -	case IMX8MM_EP: -	case IMX8MP: -	case IMX8MP_EP: +	default:  		break;  	} @@ -824,48 +804,25 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)  static void imx6_pcie_ltssm_enable(struct device *dev)  {  	struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); +	const struct imx6_pcie_drvdata *drvdata = imx6_pcie->drvdata; -	switch (imx6_pcie->drvdata->variant) { -	case IMX6Q: -	case IMX6SX: -	case IMX6QP: -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, -				   IMX6Q_GPR12_PCIE_CTL_2, -				   IMX6Q_GPR12_PCIE_CTL_2); -		break; -	case IMX7D: -	case IMX8MQ: -	case IMX8MQ_EP: -	case IMX8MM: -	case IMX8MM_EP: -	case IMX8MP: -	case IMX8MP_EP: -		reset_control_deassert(imx6_pcie->apps_reset); -		break; -	} +	if (drvdata->ltssm_mask) +		regmap_update_bits(imx6_pcie->iomuxc_gpr, drvdata->ltssm_off, drvdata->ltssm_mask, +				   drvdata->ltssm_mask); + +	reset_control_deassert(imx6_pcie->apps_reset);  }  static void imx6_pcie_ltssm_disable(struct device *dev)  {  	struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); +	const struct imx6_pcie_drvdata *drvdata = imx6_pcie->drvdata; -	switch (imx6_pcie->drvdata->variant) { -	case IMX6Q: -	case IMX6SX: -	case IMX6QP: -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, -				   IMX6Q_GPR12_PCIE_CTL_2, 0); -		break; -	case IMX7D: -	case IMX8MQ: -	case IMX8MQ_EP: -	case IMX8MM: -	case IMX8MM_EP: -	case IMX8MP: -	case IMX8MP_EP: -		reset_control_assert(imx6_pcie->apps_reset); -		break; -	} +	if (drvdata->ltssm_mask) +		regmap_update_bits(imx6_pcie->iomuxc_gpr, drvdata->ltssm_off, +				   drvdata->ltssm_mask, 0); + +	reset_control_assert(imx6_pcie->apps_reset);  }  static int imx6_pcie_start_link(struct dw_pcie *pci) @@ -977,7 +934,11 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp)  	}  	imx6_pcie_assert_core_reset(imx6_pcie); -	imx6_pcie_init_phy(imx6_pcie); + +	if (imx6_pcie->drvdata->init_phy) +		imx6_pcie->drvdata->init_phy(imx6_pcie); + +	imx6_pcie_configure_type(imx6_pcie);  	ret = imx6_pcie_clk_enable(imx6_pcie);  	if (ret) { @@ -1081,14 +1042,35 @@ static const struct pci_epc_features imx8m_pcie_epc_features = {  	.linkup_notifier = false,  	.msi_capable = true,  	.msix_capable = false, -	.reserved_bar = 1 << BAR_1 | 1 << BAR_3, +	.bar[BAR_1] = { .type = BAR_RESERVED, }, +	.bar[BAR_3] = { .type = BAR_RESERVED, },  	.align = SZ_64K,  }; +/* + * BAR#	| Default BAR enable	| Default BAR Type	| Default BAR Size	| BAR Sizing Scheme + * ================================================================================================ + * BAR0	| Enable		| 64-bit		| 1 MB			| Programmable Size + * BAR1	| Disable		| 32-bit		| 64 KB			| Fixed Size + *        BAR1 should be disabled if BAR0 is 64bit. + * BAR2	| Enable		| 32-bit		| 1 MB			| Programmable Size + * BAR3	| Enable		| 32-bit		| 64 KB			| Programmable Size + * BAR4	| Enable		| 32-bit		| 1M			| Programmable Size + * BAR5	| Enable		| 32-bit		| 64 KB			| Programmable Size + */ +static const struct pci_epc_features imx95_pcie_epc_features = { +	.msi_capable = true, +	.bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_64K, }, +	.align = SZ_4K, +}; +  static const struct pci_epc_features*  imx6_pcie_ep_get_features(struct dw_pcie_ep *ep)  { -	return &imx8m_pcie_epc_features; +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); + +	return imx6_pcie->drvdata->epc_features;  }  static const struct dw_pcie_ep_ops pcie_ep_ops = { @@ -1103,7 +1085,6 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie,  	int ret;  	unsigned int pcie_dbi2_offset;  	struct dw_pcie_ep *ep; -	struct resource *res;  	struct dw_pcie *pci = imx6_pcie->pci;  	struct dw_pcie_rp *pp = &pci->pp;  	struct device *dev = pci->dev; @@ -1122,14 +1103,20 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie,  		pcie_dbi2_offset = SZ_4K;  		break;  	} +  	pci->dbi_base2 = pci->dbi_base + pcie_dbi2_offset; -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); -	if (!res) -		return -EINVAL; -	ep->phys_base = res->start; -	ep->addr_size = resource_size(res); -	ep->page_size = SZ_64K; +	/* +	 * FIXME: Ideally, dbi2 base address should come from DT. But since only IMX95 is defining +	 * "dbi2" in DT, "dbi_base2" is set to NULL here for that platform alone so that the DWC +	 * core code can fetch that from DT. But once all platform DTs were fixed, this and the +	 * above "dbi_base2" setting should be removed. +	 */ +	if (device_property_match_string(dev, "reg-names", "dbi2") >= 0) +		pci->dbi_base2 = NULL; + +	if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_SUPPORT_64BIT)) +		dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));  	ret = dw_pcie_ep_init(ep);  	if (ret) { @@ -1251,6 +1238,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)  	struct device_node *node = dev->of_node;  	int ret;  	u16 val; +	int i;  	imx6_pcie = devm_kzalloc(dev, sizeof(*imx6_pcie), GFP_KERNEL);  	if (!imx6_pcie) @@ -1304,81 +1292,48 @@ static int imx6_pcie_probe(struct platform_device *pdev)  		return imx6_pcie->reset_gpio;  	} -	/* Fetch clocks */ -	imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus"); -	if (IS_ERR(imx6_pcie->pcie_bus)) -		return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_bus), -				     "pcie_bus clock source missing or invalid\n"); +	if (imx6_pcie->drvdata->clks_cnt >= IMX6_PCIE_MAX_CLKS) +		return dev_err_probe(dev, -ENOMEM, "clks_cnt is too big\n"); -	imx6_pcie->pcie = devm_clk_get(dev, "pcie"); -	if (IS_ERR(imx6_pcie->pcie)) -		return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie), -				     "pcie clock source missing or invalid\n"); +	for (i = 0; i < imx6_pcie->drvdata->clks_cnt; i++) +		imx6_pcie->clks[i].id = imx6_pcie->drvdata->clk_names[i]; -	switch (imx6_pcie->drvdata->variant) { -	case IMX6SX: -		imx6_pcie->pcie_inbound_axi = devm_clk_get(dev, -							   "pcie_inbound_axi"); -		if (IS_ERR(imx6_pcie->pcie_inbound_axi)) -			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_inbound_axi), -					     "pcie_inbound_axi clock missing or invalid\n"); -		break; -	case IMX8MQ: -	case IMX8MQ_EP: -		imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux"); -		if (IS_ERR(imx6_pcie->pcie_aux)) -			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux), -					     "pcie_aux clock source missing or invalid\n"); -		fallthrough; -	case IMX7D: -		if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) -			imx6_pcie->controller_id = 1; +	/* Fetch clocks */ +	ret = devm_clk_bulk_get(dev, imx6_pcie->drvdata->clks_cnt, imx6_pcie->clks); +	if (ret) +		return ret; -		imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev, -									    "pciephy"); -		if (IS_ERR(imx6_pcie->pciephy_reset)) { -			dev_err(dev, "Failed to get PCIEPHY reset control\n"); -			return PTR_ERR(imx6_pcie->pciephy_reset); -		} +	if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_PHYDRV)) { +		imx6_pcie->phy = devm_phy_get(dev, "pcie-phy"); +		if (IS_ERR(imx6_pcie->phy)) +			return dev_err_probe(dev, PTR_ERR(imx6_pcie->phy), +					     "failed to get pcie phy\n"); +	} -		imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev, -									 "apps"); -		if (IS_ERR(imx6_pcie->apps_reset)) { -			dev_err(dev, "Failed to get PCIE APPS reset control\n"); -			return PTR_ERR(imx6_pcie->apps_reset); -		} -		break; -	case IMX8MM: -	case IMX8MM_EP: -	case IMX8MP: -	case IMX8MP_EP: -		imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux"); -		if (IS_ERR(imx6_pcie->pcie_aux)) -			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux), -					     "pcie_aux clock source missing or invalid\n"); -		imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev, -									 "apps"); +	if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_APP_RESET)) { +		imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev, "apps");  		if (IS_ERR(imx6_pcie->apps_reset))  			return dev_err_probe(dev, PTR_ERR(imx6_pcie->apps_reset),  					     "failed to get pcie apps reset control\n"); +	} -		imx6_pcie->phy = devm_phy_get(dev, "pcie-phy"); -		if (IS_ERR(imx6_pcie->phy)) -			return dev_err_probe(dev, PTR_ERR(imx6_pcie->phy), -					     "failed to get pcie phy\n"); +	if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_PHY_RESET)) { +		imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev, "pciephy"); +		if (IS_ERR(imx6_pcie->pciephy_reset)) +			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pciephy_reset), +					     "Failed to get PCIEPHY reset control\n"); +	} +	switch (imx6_pcie->drvdata->variant) { +	case IMX8MQ: +	case IMX8MQ_EP: +	case IMX7D: +		if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) +			imx6_pcie->controller_id = 1;  		break;  	default:  		break;  	} -	/* Don't fetch the pcie_phy clock, if it has abstract PHY driver */ -	if (imx6_pcie->phy == NULL) { -		imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy"); -		if (IS_ERR(imx6_pcie->pcie_phy)) -			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy), -					     "pcie_phy clock source missing or invalid\n"); -	} -  	/* Grab turnoff reset */  	imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff"); @@ -1387,12 +1342,32 @@ static int imx6_pcie_probe(struct platform_device *pdev)  		return PTR_ERR(imx6_pcie->turnoff_reset);  	} +	if (imx6_pcie->drvdata->gpr) {  	/* Grab GPR config register range */ -	imx6_pcie->iomuxc_gpr = -		 syscon_regmap_lookup_by_compatible(imx6_pcie->drvdata->gpr); -	if (IS_ERR(imx6_pcie->iomuxc_gpr)) { -		dev_err(dev, "unable to find iomuxc registers\n"); -		return PTR_ERR(imx6_pcie->iomuxc_gpr); +		imx6_pcie->iomuxc_gpr = +			 syscon_regmap_lookup_by_compatible(imx6_pcie->drvdata->gpr); +		if (IS_ERR(imx6_pcie->iomuxc_gpr)) +			return dev_err_probe(dev, PTR_ERR(imx6_pcie->iomuxc_gpr), +					     "unable to find iomuxc registers\n"); +	} + +	if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_SERDES)) { +		void __iomem *off = devm_platform_ioremap_resource_byname(pdev, "app"); + +		if (IS_ERR(off)) +			return dev_err_probe(dev, PTR_ERR(off), +					     "unable to find serdes registers\n"); + +		static const struct regmap_config regmap_config = { +			.reg_bits = 32, +			.val_bits = 32, +			.reg_stride = 4, +		}; + +		imx6_pcie->iomuxc_gpr = devm_regmap_init_mmio(dev, off, ®map_config); +		if (IS_ERR(imx6_pcie->iomuxc_gpr)) +			return dev_err_probe(dev, PTR_ERR(imx6_pcie->iomuxc_gpr), +					     "unable to find iomuxc registers\n");  	}  	/* Grab PCIe PHY Tx Settings */ @@ -1469,6 +1444,11 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)  	imx6_pcie_assert_core_reset(imx6_pcie);  } +static const char * const imx6q_clks[] = {"pcie_bus", "pcie", "pcie_phy"}; +static const char * const imx8mm_clks[] = {"pcie_bus", "pcie", "pcie_aux"}; +static const char * const imx8mq_clks[] = {"pcie_bus", "pcie", "pcie_phy", "pcie_aux"}; +static const char * const imx6sx_clks[] = {"pcie_bus", "pcie", "pcie_phy", "pcie_inbound_axi"}; +  static const struct imx6_pcie_drvdata drvdata[] = {  	[IMX6Q] = {  		.variant = IMX6Q, @@ -1476,6 +1456,13 @@ static const struct imx6_pcie_drvdata drvdata[] = {  			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,  		.dbi_length = 0x200,  		.gpr = "fsl,imx6q-iomuxc-gpr", +		.clk_names = imx6q_clks, +		.clks_cnt = ARRAY_SIZE(imx6q_clks), +		.ltssm_off = IOMUXC_GPR12, +		.ltssm_mask = IMX6Q_GPR12_PCIE_CTL_2, +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +		.init_phy = imx6_pcie_init_phy,  	},  	[IMX6SX] = {  		.variant = IMX6SX, @@ -1483,6 +1470,13 @@ static const struct imx6_pcie_drvdata drvdata[] = {  			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE |  			 IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,  		.gpr = "fsl,imx6q-iomuxc-gpr", +		.clk_names = imx6sx_clks, +		.clks_cnt = ARRAY_SIZE(imx6sx_clks), +		.ltssm_off = IOMUXC_GPR12, +		.ltssm_mask = IMX6Q_GPR12_PCIE_CTL_2, +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +		.init_phy = imx6sx_pcie_init_phy,  	},  	[IMX6QP] = {  		.variant = IMX6QP, @@ -1491,40 +1485,122 @@ static const struct imx6_pcie_drvdata drvdata[] = {  			 IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,  		.dbi_length = 0x200,  		.gpr = "fsl,imx6q-iomuxc-gpr", +		.clk_names = imx6q_clks, +		.clks_cnt = ARRAY_SIZE(imx6q_clks), +		.ltssm_off = IOMUXC_GPR12, +		.ltssm_mask = IMX6Q_GPR12_PCIE_CTL_2, +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +		.init_phy = imx6_pcie_init_phy,  	},  	[IMX7D] = {  		.variant = IMX7D, -		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, +		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND | +			 IMX6_PCIE_FLAG_HAS_APP_RESET | +			 IMX6_PCIE_FLAG_HAS_PHY_RESET,  		.gpr = "fsl,imx7d-iomuxc-gpr", +		.clk_names = imx6q_clks, +		.clks_cnt = ARRAY_SIZE(imx6q_clks), +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +		.init_phy = imx7d_pcie_init_phy,  	},  	[IMX8MQ] = {  		.variant = IMX8MQ, +		.flags = IMX6_PCIE_FLAG_HAS_APP_RESET | +			 IMX6_PCIE_FLAG_HAS_PHY_RESET,  		.gpr = "fsl,imx8mq-iomuxc-gpr", +		.clk_names = imx8mq_clks, +		.clks_cnt = ARRAY_SIZE(imx8mq_clks), +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +		.mode_off[1] = IOMUXC_GPR12, +		.mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, +		.init_phy = imx8mq_pcie_init_phy,  	},  	[IMX8MM] = {  		.variant = IMX8MM, -		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, +		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND | +			 IMX6_PCIE_FLAG_HAS_PHYDRV | +			 IMX6_PCIE_FLAG_HAS_APP_RESET,  		.gpr = "fsl,imx8mm-iomuxc-gpr", +		.clk_names = imx8mm_clks, +		.clks_cnt = ARRAY_SIZE(imx8mm_clks), +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,  	},  	[IMX8MP] = {  		.variant = IMX8MP, -		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, +		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND | +			 IMX6_PCIE_FLAG_HAS_PHYDRV | +			 IMX6_PCIE_FLAG_HAS_APP_RESET,  		.gpr = "fsl,imx8mp-iomuxc-gpr", +		.clk_names = imx8mm_clks, +		.clks_cnt = ARRAY_SIZE(imx8mm_clks), +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +	}, +	[IMX95] = { +		.variant = IMX95, +		.flags = IMX6_PCIE_FLAG_HAS_SERDES, +		.clk_names = imx8mq_clks, +		.clks_cnt = ARRAY_SIZE(imx8mq_clks), +		.ltssm_off = IMX95_PE0_GEN_CTRL_3, +		.ltssm_mask = IMX95_PCIE_LTSSM_EN, +		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1, +		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE, +		.init_phy = imx95_pcie_init_phy,  	},  	[IMX8MQ_EP] = {  		.variant = IMX8MQ_EP, +		.flags = IMX6_PCIE_FLAG_HAS_APP_RESET | +			 IMX6_PCIE_FLAG_HAS_PHY_RESET,  		.mode = DW_PCIE_EP_TYPE,  		.gpr = "fsl,imx8mq-iomuxc-gpr", +		.clk_names = imx8mq_clks, +		.clks_cnt = ARRAY_SIZE(imx8mq_clks), +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +		.mode_off[1] = IOMUXC_GPR12, +		.mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, +		.epc_features = &imx8m_pcie_epc_features, +		.init_phy = imx8mq_pcie_init_phy,  	},  	[IMX8MM_EP] = {  		.variant = IMX8MM_EP, +		.flags = IMX6_PCIE_FLAG_HAS_PHYDRV,  		.mode = DW_PCIE_EP_TYPE,  		.gpr = "fsl,imx8mm-iomuxc-gpr", +		.clk_names = imx8mm_clks, +		.clks_cnt = ARRAY_SIZE(imx8mm_clks), +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +		.epc_features = &imx8m_pcie_epc_features,  	},  	[IMX8MP_EP] = {  		.variant = IMX8MP_EP, +		.flags = IMX6_PCIE_FLAG_HAS_PHYDRV,  		.mode = DW_PCIE_EP_TYPE,  		.gpr = "fsl,imx8mp-iomuxc-gpr", +		.clk_names = imx8mm_clks, +		.clks_cnt = ARRAY_SIZE(imx8mm_clks), +		.mode_off[0] = IOMUXC_GPR12, +		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, +		.epc_features = &imx8m_pcie_epc_features, +	}, +	[IMX95_EP] = { +		.variant = IMX95_EP, +		.flags = IMX6_PCIE_FLAG_HAS_SERDES | +			 IMX6_PCIE_FLAG_SUPPORT_64BIT, +		.clk_names = imx8mq_clks, +		.clks_cnt = ARRAY_SIZE(imx8mq_clks), +		.ltssm_off = IMX95_PE0_GEN_CTRL_3, +		.ltssm_mask = IMX95_PCIE_LTSSM_EN, +		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1, +		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE, +		.init_phy = imx95_pcie_init_phy, +		.epc_features = &imx95_pcie_epc_features, +		.mode = DW_PCIE_EP_TYPE,  	},  }; @@ -1536,9 +1612,11 @@ static const struct of_device_id imx6_pcie_of_match[] = {  	{ .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },  	{ .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], },  	{ .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], }, +	{ .compatible = "fsl,imx95-pcie", .data = &drvdata[IMX95], },  	{ .compatible = "fsl,imx8mq-pcie-ep", .data = &drvdata[IMX8MQ_EP], },  	{ .compatible = "fsl,imx8mm-pcie-ep", .data = &drvdata[IMX8MM_EP], },  	{ .compatible = "fsl,imx8mp-pcie-ep", .data = &drvdata[IMX8MP_EP], }, +	{ .compatible = "fsl,imx95-pcie-ep", .data = &drvdata[IMX95_EP], },  	{},  }; diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index c0c62533a3f1..844de4418724 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -924,12 +924,12 @@ static const struct pci_epc_features ks_pcie_am654_epc_features = {  	.linkup_notifier = false,  	.msi_capable = true,  	.msix_capable = true, -	.reserved_bar = 1 << BAR_0 | 1 << BAR_1, -	.bar_fixed_64bit = 1 << BAR_0, -	.bar_fixed_size[2] = SZ_1M, -	.bar_fixed_size[3] = SZ_64K, -	.bar_fixed_size[4] = 256, -	.bar_fixed_size[5] = SZ_1M, +	.bar[BAR_0] = { .type = BAR_RESERVED, }, +	.bar[BAR_1] = { .type = BAR_RESERVED, }, +	.bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, +	.bar[BAR_3] = { .type = BAR_FIXED, .fixed_size = SZ_64K, }, +	.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256, }, +	.bar[BAR_5] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },  	.align = SZ_1M,  }; diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c index 2e398494e7c0..1f6ee1460ec2 100644 --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c @@ -250,7 +250,10 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)  	pci->dev = dev;  	pci->ops = pcie->drvdata->dw_pcie_ops; -	ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4); +	ls_epc->bar[BAR_2].only_64bit = true; +	ls_epc->bar[BAR_3].type = BAR_RESERVED; +	ls_epc->bar[BAR_4].only_64bit = true; +	ls_epc->bar[BAR_5].type = BAR_RESERVED;  	ls_epc->linkup_notifier = true;  	pcie->pci = pci; diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 9a437cfce073..746a11dcb67f 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -629,8 +629,13 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)  		nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>  			PCI_REBAR_CTRL_NBAR_SHIFT; +		/* +		 * PCIe r6.0, sec 7.8.6.2 require us to support at least one +		 * size in the range from 1 MB to 512 GB. Advertise support +		 * for 1 MB BAR size only. +		 */  		for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) -			dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0); +			dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, BIT(4));  	}  	/* diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index d5fc31f8345f..d15a5c2d5b48 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -328,7 +328,7 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct device *dev = pci->dev;  	struct platform_device *pdev = to_platform_device(dev); -	u64 *msi_vaddr; +	u64 *msi_vaddr = NULL;  	int ret;  	u32 ctrl, num_ctrls; @@ -379,15 +379,20 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)  	 * memory.  	 */  	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); -	if (ret) -		dev_warn(dev, "Failed to set DMA mask to 32-bit. Devices with only 32-bit MSI support may not work properly\n"); +	if (!ret) +		msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data, +						GFP_KERNEL); -	msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data, -					GFP_KERNEL);  	if (!msi_vaddr) { -		dev_err(dev, "Failed to alloc and map MSI data\n"); -		dw_pcie_free_msi(pp); -		return -ENOMEM; +		dev_warn(dev, "Failed to allocate 32-bit MSI address\n"); +		dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); +		msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data, +						GFP_KERNEL); +		if (!msi_vaddr) { +			dev_err(dev, "Failed to allocate MSI address\n"); +			dw_pcie_free_msi(pp); +			return -ENOMEM; +		}  	}  	return 0; diff --git a/drivers/pci/controller/dwc/pcie-keembay.c b/drivers/pci/controller/dwc/pcie-keembay.c index 208d3b0ba196..5e8e54f597dd 100644 --- a/drivers/pci/controller/dwc/pcie-keembay.c +++ b/drivers/pci/controller/dwc/pcie-keembay.c @@ -312,8 +312,12 @@ static const struct pci_epc_features keembay_pcie_epc_features = {  	.linkup_notifier	= false,  	.msi_capable		= true,  	.msix_capable		= true, -	.reserved_bar		= BIT(BAR_1) | BIT(BAR_3) | BIT(BAR_5), -	.bar_fixed_64bit	= BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4), +	.bar[BAR_0]		= { .only_64bit = true, }, +	.bar[BAR_1]		= { .type = BAR_RESERVED, }, +	.bar[BAR_2]		= { .only_64bit = true, }, +	.bar[BAR_3]		= { .type = BAR_RESERVED, }, +	.bar[BAR_4]		= { .only_64bit = true, }, +	.bar[BAR_5]		= { .type = BAR_RESERVED, },  	.align			= SZ_16K,  }; diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 2ce2a3bd932b..14772edcf0d3 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -53,6 +53,7 @@  #define PARF_SLV_ADDR_SPACE_SIZE		0x358  #define PARF_DEVICE_TYPE			0x1000  #define PARF_BDF_TO_SID_TABLE_N			0x2000 +#define PARF_BDF_TO_SID_CFG			0x2c00  /* ELBI registers */  #define ELBI_SYS_CTRL				0x04 @@ -120,6 +121,9 @@  /* PARF_DEVICE_TYPE register fields */  #define DEVICE_TYPE_RC				0x4 +/* PARF_BDF_TO_SID_CFG fields */ +#define BDF_TO_SID_BYPASS			BIT(0) +  /* ELBI_SYS_CTRL register fields */  #define ELBI_SYS_CTRL_LT_ENABLE			BIT(0) @@ -229,6 +233,7 @@ struct qcom_pcie_ops {  struct qcom_pcie_cfg {  	const struct qcom_pcie_ops *ops; +	bool no_l0s;  };  struct qcom_pcie { @@ -272,6 +277,26 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)  	return 0;  } +static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci) +{ +	struct qcom_pcie *pcie = to_qcom_pcie(pci); +	u16 offset; +	u32 val; + +	if (!pcie->cfg->no_l0s) +		return; + +	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + +	dw_pcie_dbi_ro_wr_en(pci); + +	val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); +	val &= ~PCI_EXP_LNKCAP_ASPM_L0S; +	writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP); + +	dw_pcie_dbi_ro_wr_dis(pci); +} +  static void qcom_pcie_clear_hpc(struct dw_pcie *pci)  {  	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); @@ -961,6 +986,7 @@ err_disable_regulators:  static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)  { +	qcom_pcie_clear_aspm_l0s(pcie->pci);  	qcom_pcie_clear_hpc(pcie->pci);  	return 0; @@ -1008,11 +1034,17 @@ static int qcom_pcie_config_sid_1_9_0(struct qcom_pcie *pcie)  	u8 qcom_pcie_crc8_table[CRC8_TABLE_SIZE];  	int i, nr_map, size = 0;  	u32 smmu_sid_base; +	u32 val;  	of_get_property(dev->of_node, "iommu-map", &size);  	if (!size)  		return 0; +	/* Enable BDF to SID translation by disabling bypass mode (default) */ +	val = readl(pcie->parf + PARF_BDF_TO_SID_CFG); +	val &= ~BDF_TO_SID_BYPASS; +	writel(val, pcie->parf + PARF_BDF_TO_SID_CFG); +  	map = kzalloc(size, GFP_KERNEL);  	if (!map)  		return -ENOMEM; @@ -1358,6 +1390,11 @@ static const struct qcom_pcie_cfg cfg_2_9_0 = {  	.ops = &ops_2_9_0,  }; +static const struct qcom_pcie_cfg cfg_sc8280xp = { +	.ops = &ops_1_9_0, +	.no_l0s = true, +}; +  static const struct dw_pcie_ops dw_pcie_ops = {  	.link_up = qcom_pcie_link_up,  	.start_link = qcom_pcie_start_link, @@ -1629,11 +1666,11 @@ static const struct of_device_id qcom_pcie_match[] = {  	{ .compatible = "qcom,pcie-ipq8074-gen3", .data = &cfg_2_9_0 },  	{ .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 },  	{ .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 }, -	{ .compatible = "qcom,pcie-sa8540p", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sa8540p", .data = &cfg_sc8280xp },  	{ .compatible = "qcom,pcie-sa8775p", .data = &cfg_1_9_0},  	{ .compatible = "qcom,pcie-sc7280", .data = &cfg_1_9_0 },  	{ .compatible = "qcom,pcie-sc8180x", .data = &cfg_1_9_0 }, -	{ .compatible = "qcom,pcie-sc8280xp", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sc8280xp", .data = &cfg_sc8280xp },  	{ .compatible = "qcom,pcie-sdm845", .data = &cfg_2_7_0 },  	{ .compatible = "qcom,pcie-sdx55", .data = &cfg_1_9_0 },  	{ .compatible = "qcom,pcie-sm8150", .data = &cfg_1_9_0 }, @@ -1642,6 +1679,7 @@ static const struct of_device_id qcom_pcie_match[] = {  	{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &cfg_1_9_0 },  	{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &cfg_1_9_0 },  	{ .compatible = "qcom,pcie-sm8550", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-x1e80100", .data = &cfg_1_9_0 },  	{ }  }; diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c index e9166619b1f9..0be760ed420b 100644 --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c @@ -383,7 +383,9 @@ static const struct pci_epc_features rcar_gen4_pcie_epc_features = {  	.linkup_notifier = false,  	.msi_capable = true,  	.msix_capable = false, -	.reserved_bar = 1 << BAR_1 | 1 << BAR_3 | 1 << BAR_5, +	.bar[BAR_1] = { .type = BAR_RESERVED, }, +	.bar[BAR_3] = { .type = BAR_RESERVED, }, +	.bar[BAR_5] = { .type = BAR_RESERVED, },  	.align = SZ_1M,  }; diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index 7afa9e9aabe2..1f7b662cb8e1 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -2007,9 +2007,13 @@ static const struct pci_epc_features tegra_pcie_epc_features = {  	.core_init_notifier = true,  	.msi_capable = false,  	.msix_capable = false, -	.reserved_bar = 1 << BAR_2 | 1 << BAR_3 | 1 << BAR_4 | 1 << BAR_5, -	.bar_fixed_64bit = 1 << BAR_0, -	.bar_fixed_size[0] = SZ_1M, +	.bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M, +			.only_64bit = true, }, +	.bar[BAR_1] = { .type = BAR_RESERVED, }, +	.bar[BAR_2] = { .type = BAR_RESERVED, }, +	.bar[BAR_3] = { .type = BAR_RESERVED, }, +	.bar[BAR_4] = { .type = BAR_RESERVED, }, +	.bar[BAR_5] = { .type = BAR_RESERVED, },  };  static const struct pci_epc_features* diff --git a/drivers/pci/controller/dwc/pcie-uniphier-ep.c b/drivers/pci/controller/dwc/pcie-uniphier-ep.c index 3fced0d3e851..639bc2e12476 100644 --- a/drivers/pci/controller/dwc/pcie-uniphier-ep.c +++ b/drivers/pci/controller/dwc/pcie-uniphier-ep.c @@ -411,8 +411,12 @@ static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = {  		.msi_capable = true,  		.msix_capable = false,  		.align = 1 << 16, -		.bar_fixed_64bit = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4), -		.reserved_bar =  BIT(BAR_4), +		.bar[BAR_0] = { .only_64bit = true, }, +		.bar[BAR_1] = { .type = BAR_RESERVED, }, +		.bar[BAR_2] = { .only_64bit = true, }, +		.bar[BAR_3] = { .type = BAR_RESERVED, }, +		.bar[BAR_4] = { .type = BAR_RESERVED, }, +		.bar[BAR_5] = { .type = BAR_RESERVED, },  	},  }; @@ -425,7 +429,12 @@ static const struct uniphier_pcie_ep_soc_data uniphier_nx1_data = {  		.msi_capable = true,  		.msix_capable = false,  		.align = 1 << 12, -		.bar_fixed_64bit = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4), +		.bar[BAR_0] = { .only_64bit = true, }, +		.bar[BAR_1] = { .type = BAR_RESERVED, }, +		.bar[BAR_2] = { .only_64bit = true, }, +		.bar[BAR_3] = { .type = BAR_RESERVED, }, +		.bar[BAR_4] = { .only_64bit = true, }, +		.bar[BAR_5] = { .type = BAR_RESERVED, },  	},  };  | 
