diff mbox series

[2/5] PCI: j721e: Add PCIe support for J7200

Message ID 20210706105035.9915-3-kishon@ti.com (mailing list archive)
State New, archived
Headers show
Series PCI: Add support for J7200 and AM64 | expand

Commit Message

Kishon Vijay Abraham I July 6, 2021, 10:50 a.m. UTC
J7200 has the same PCIe IP as in J721E with minor changes in the
wrapper. J7200 allows byte access of bridge configuration space
registers and the register field for LINK_DOWN interrupt is different.
J7200 also requires "quirk_detect_quiet_flag" to be set. Configure these
changes as part of driver data applicable only to J7200.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/pci/controller/cadence/pci-j721e.c | 44 ++++++++++++++++++++--
 1 file changed, 40 insertions(+), 4 deletions(-)

Comments

Bjorn Helgaas July 7, 2021, 12:01 p.m. UTC | #1
On Tue, Jul 06, 2021 at 04:20:32PM +0530, Kishon Vijay Abraham I wrote:
> J7200 has the same PCIe IP as in J721E with minor changes in the
> wrapper. J7200 allows byte access of bridge configuration space
> registers and the register field for LINK_DOWN interrupt is different.
> J7200 also requires "quirk_detect_quiet_flag" to be set. Configure these
> changes as part of driver data applicable only to J7200.
> 
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
>  drivers/pci/controller/cadence/pci-j721e.c | 44 ++++++++++++++++++++--
>  1 file changed, 40 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
> index 35e61048e133..803da33b86d8 100644
> --- a/drivers/pci/controller/cadence/pci-j721e.c
> +++ b/drivers/pci/controller/cadence/pci-j721e.c
> @@ -27,6 +27,7 @@
>  #define STATUS_REG_SYS_2	0x508
>  #define STATUS_CLR_REG_SYS_2	0x708
>  #define LINK_DOWN		BIT(1)
> +#define J7200_LINK_DOWN		BIT(10)
>  
>  #define J721E_PCIE_USER_CMD_STATUS	0x4
>  #define LINK_TRAINING_ENABLE		BIT(0)
> @@ -57,6 +58,7 @@ struct j721e_pcie {
>  	struct cdns_pcie	*cdns_pcie;
>  	void __iomem		*user_cfg_base;
>  	void __iomem		*intd_cfg_base;
> +	u32			link_irq_reg_field;

This seems to be a device-specific "link down" bit, so maybe a more
descriptive name that suggests "link down"?

>  };
>  
>  enum j721e_pcie_mode {
> @@ -67,6 +69,9 @@ enum j721e_pcie_mode {
>  struct j721e_pcie_data {
>  	enum j721e_pcie_mode	mode;
>  	bool quirk_retrain_flag;
> +	bool			quirk_detect_quiet_flag;
> +	u32			link_irq_reg_field;
> +	bool			byte_access_allowed;

Maybe re-indent quirk_retrain_flag so the struct is consistent?

I know there's a pattern of using "bool" in these structs, but I don't
think it's really any better than "unsigned int :1" and it takes more
space.

https://lore.kernel.org/r/CA+55aFzKQ6Pj18TB8p4Yr0M4t+S+BsiHH=BJNmn=76-NcjTj-g@mail.gmail.com/
https://lore.kernel.org/r/CA+55aFxnePDimkVKVtv3gNmRGcwc8KQ5mHYvUxY8sAQg6yvVYg@mail.gmail.com/

>  };
>  
>  static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset)
> @@ -98,12 +103,12 @@ static irqreturn_t j721e_pcie_link_irq_handler(int irq, void *priv)
>  	u32 reg;
>  
>  	reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_2);
> -	if (!(reg & LINK_DOWN))
> +	if (!(reg & pcie->link_irq_reg_field))
>  		return IRQ_NONE;
>  
>  	dev_err(dev, "LINK DOWN!\n");
>  
> -	j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_2, LINK_DOWN);
> +	j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_2, pcie->link_irq_reg_field);
>  	return IRQ_HANDLED;
>  }
>  
> @@ -112,7 +117,7 @@ static void j721e_pcie_config_link_irq(struct j721e_pcie *pcie)
>  	u32 reg;
>  
>  	reg = j721e_pcie_intd_readl(pcie, ENABLE_REG_SYS_2);
> -	reg |= LINK_DOWN;
> +	reg |= pcie->link_irq_reg_field;
>  	j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_2, reg);
>  }
>  
> @@ -284,10 +289,25 @@ static struct pci_ops cdns_ti_pcie_host_ops = {
>  static const struct j721e_pcie_data j721e_pcie_rc_data = {
>  	.mode = PCI_MODE_RC,
>  	.quirk_retrain_flag = true,
> +	.byte_access_allowed = false,
> +	.link_irq_reg_field = LINK_DOWN,
>  };
>  
>  static const struct j721e_pcie_data j721e_pcie_ep_data = {
>  	.mode = PCI_MODE_EP,
> +	.link_irq_reg_field = LINK_DOWN,
> +};
> +
> +static const struct j721e_pcie_data j7200_pcie_rc_data = {
> +	.mode = PCI_MODE_RC,
> +	.quirk_detect_quiet_flag = true,
> +	.link_irq_reg_field = J7200_LINK_DOWN,
> +	.byte_access_allowed = true,
> +};
> +
> +static const struct j721e_pcie_data j7200_pcie_ep_data = {
> +	.mode = PCI_MODE_EP,
> +	.quirk_detect_quiet_flag = true,
>  };
>  
>  static const struct of_device_id of_j721e_pcie_match[] = {
> @@ -299,6 +319,14 @@ static const struct of_device_id of_j721e_pcie_match[] = {
>  		.compatible = "ti,j721e-pcie-ep",
>  		.data = &j721e_pcie_ep_data,
>  	},
> +	{
> +		.compatible = "ti,j7200-pcie-host",
> +		.data = &j7200_pcie_rc_data,
> +	},
> +	{
> +		.compatible = "ti,j7200-pcie-ep",
> +		.data = &j7200_pcie_ep_data,
> +	},
>  	{},
>  };
>  
> @@ -309,10 +337,12 @@ static int j721e_pcie_probe(struct platform_device *pdev)
>  	struct pci_host_bridge *bridge;
>  	struct j721e_pcie_data *data;
>  	struct cdns_pcie *cdns_pcie;
> +	bool byte_access_allowed;
>  	struct j721e_pcie *pcie;
>  	struct cdns_pcie_rc *rc;
>  	struct cdns_pcie_ep *ep;
>  	struct gpio_desc *gpiod;
> +	u32 link_irq_reg_field;
>  	void __iomem *base;
>  	struct clk *clk;
>  	u32 num_lanes;
> @@ -325,6 +355,8 @@ static int j721e_pcie_probe(struct platform_device *pdev)
>  		return -EINVAL;
>  
>  	mode = (u32)data->mode;
> +	byte_access_allowed = data->byte_access_allowed;
> +	link_irq_reg_field = data->link_irq_reg_field;
>  
>  	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
>  	if (!pcie)
> @@ -332,6 +364,7 @@ static int j721e_pcie_probe(struct platform_device *pdev)
>  
>  	pcie->dev = dev;
>  	pcie->mode = mode;
> +	pcie->link_irq_reg_field = link_irq_reg_field;
>  
>  	base = devm_platform_ioremap_resource_byname(pdev, "intd_cfg");
>  	if (IS_ERR(base))
> @@ -391,9 +424,11 @@ static int j721e_pcie_probe(struct platform_device *pdev)
>  			goto err_get_sync;
>  		}
>  
> -		bridge->ops = &cdns_ti_pcie_host_ops;
> +		if (!byte_access_allowed)

Why bother with the "byte_access_allowed" local variable?  Could just
use "data->byte_access_allowed" here, as the code below uses
"data->quirk_retrain_flag", etc.

Same with "link_irq_reg_field" above, I guess.

> +			bridge->ops = &cdns_ti_pcie_host_ops;
>  		rc = pci_host_bridge_priv(bridge);
>  		rc->quirk_retrain_flag = data->quirk_retrain_flag;
> +		rc->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
>  
>  		cdns_pcie = &rc->pcie;
>  		cdns_pcie->dev = dev;
> @@ -459,6 +494,7 @@ static int j721e_pcie_probe(struct platform_device *pdev)
>  			ret = -ENOMEM;
>  			goto err_get_sync;
>  		}
> +		ep->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
>  
>  		cdns_pcie = &ep->pcie;
>  		cdns_pcie->dev = dev;
> -- 
> 2.17.1
>
diff mbox series

Patch

diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
index 35e61048e133..803da33b86d8 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -27,6 +27,7 @@ 
 #define STATUS_REG_SYS_2	0x508
 #define STATUS_CLR_REG_SYS_2	0x708
 #define LINK_DOWN		BIT(1)
+#define J7200_LINK_DOWN		BIT(10)
 
 #define J721E_PCIE_USER_CMD_STATUS	0x4
 #define LINK_TRAINING_ENABLE		BIT(0)
@@ -57,6 +58,7 @@  struct j721e_pcie {
 	struct cdns_pcie	*cdns_pcie;
 	void __iomem		*user_cfg_base;
 	void __iomem		*intd_cfg_base;
+	u32			link_irq_reg_field;
 };
 
 enum j721e_pcie_mode {
@@ -67,6 +69,9 @@  enum j721e_pcie_mode {
 struct j721e_pcie_data {
 	enum j721e_pcie_mode	mode;
 	bool quirk_retrain_flag;
+	bool			quirk_detect_quiet_flag;
+	u32			link_irq_reg_field;
+	bool			byte_access_allowed;
 };
 
 static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset)
@@ -98,12 +103,12 @@  static irqreturn_t j721e_pcie_link_irq_handler(int irq, void *priv)
 	u32 reg;
 
 	reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_2);
-	if (!(reg & LINK_DOWN))
+	if (!(reg & pcie->link_irq_reg_field))
 		return IRQ_NONE;
 
 	dev_err(dev, "LINK DOWN!\n");
 
-	j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_2, LINK_DOWN);
+	j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_2, pcie->link_irq_reg_field);
 	return IRQ_HANDLED;
 }
 
@@ -112,7 +117,7 @@  static void j721e_pcie_config_link_irq(struct j721e_pcie *pcie)
 	u32 reg;
 
 	reg = j721e_pcie_intd_readl(pcie, ENABLE_REG_SYS_2);
-	reg |= LINK_DOWN;
+	reg |= pcie->link_irq_reg_field;
 	j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_2, reg);
 }
 
@@ -284,10 +289,25 @@  static struct pci_ops cdns_ti_pcie_host_ops = {
 static const struct j721e_pcie_data j721e_pcie_rc_data = {
 	.mode = PCI_MODE_RC,
 	.quirk_retrain_flag = true,
+	.byte_access_allowed = false,
+	.link_irq_reg_field = LINK_DOWN,
 };
 
 static const struct j721e_pcie_data j721e_pcie_ep_data = {
 	.mode = PCI_MODE_EP,
+	.link_irq_reg_field = LINK_DOWN,
+};
+
+static const struct j721e_pcie_data j7200_pcie_rc_data = {
+	.mode = PCI_MODE_RC,
+	.quirk_detect_quiet_flag = true,
+	.link_irq_reg_field = J7200_LINK_DOWN,
+	.byte_access_allowed = true,
+};
+
+static const struct j721e_pcie_data j7200_pcie_ep_data = {
+	.mode = PCI_MODE_EP,
+	.quirk_detect_quiet_flag = true,
 };
 
 static const struct of_device_id of_j721e_pcie_match[] = {
@@ -299,6 +319,14 @@  static const struct of_device_id of_j721e_pcie_match[] = {
 		.compatible = "ti,j721e-pcie-ep",
 		.data = &j721e_pcie_ep_data,
 	},
+	{
+		.compatible = "ti,j7200-pcie-host",
+		.data = &j7200_pcie_rc_data,
+	},
+	{
+		.compatible = "ti,j7200-pcie-ep",
+		.data = &j7200_pcie_ep_data,
+	},
 	{},
 };
 
@@ -309,10 +337,12 @@  static int j721e_pcie_probe(struct platform_device *pdev)
 	struct pci_host_bridge *bridge;
 	struct j721e_pcie_data *data;
 	struct cdns_pcie *cdns_pcie;
+	bool byte_access_allowed;
 	struct j721e_pcie *pcie;
 	struct cdns_pcie_rc *rc;
 	struct cdns_pcie_ep *ep;
 	struct gpio_desc *gpiod;
+	u32 link_irq_reg_field;
 	void __iomem *base;
 	struct clk *clk;
 	u32 num_lanes;
@@ -325,6 +355,8 @@  static int j721e_pcie_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	mode = (u32)data->mode;
+	byte_access_allowed = data->byte_access_allowed;
+	link_irq_reg_field = data->link_irq_reg_field;
 
 	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
 	if (!pcie)
@@ -332,6 +364,7 @@  static int j721e_pcie_probe(struct platform_device *pdev)
 
 	pcie->dev = dev;
 	pcie->mode = mode;
+	pcie->link_irq_reg_field = link_irq_reg_field;
 
 	base = devm_platform_ioremap_resource_byname(pdev, "intd_cfg");
 	if (IS_ERR(base))
@@ -391,9 +424,11 @@  static int j721e_pcie_probe(struct platform_device *pdev)
 			goto err_get_sync;
 		}
 
-		bridge->ops = &cdns_ti_pcie_host_ops;
+		if (!byte_access_allowed)
+			bridge->ops = &cdns_ti_pcie_host_ops;
 		rc = pci_host_bridge_priv(bridge);
 		rc->quirk_retrain_flag = data->quirk_retrain_flag;
+		rc->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
 
 		cdns_pcie = &rc->pcie;
 		cdns_pcie->dev = dev;
@@ -459,6 +494,7 @@  static int j721e_pcie_probe(struct platform_device *pdev)
 			ret = -ENOMEM;
 			goto err_get_sync;
 		}
+		ep->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
 
 		cdns_pcie = &ep->pcie;
 		cdns_pcie->dev = dev;