* [PATCH 0/1] pci: agilex_rp: add pci root port support for agilex platform @ 2023-06-16 6:33 sharath.kumar.d.m 2023-06-16 6:33 ` [PATCH 1/1] pci: agilex_pci: add pcie rootport support for agilex sharath.kumar.d.m 0 siblings, 1 reply; 56+ messages in thread From: sharath.kumar.d.m @ 2023-06-16 6:33 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write D M Sharath Kumar (1): pci: agilex_pci: add pcie rootport support for agilex drivers/pci/controller/pcie-altera.c | 278 ++++++++++++++++++++++++++- 1 file changed, 268 insertions(+), 10 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 1/1] pci: agilex_pci: add pcie rootport support for agilex 2023-06-16 6:33 [PATCH 0/1] pci: agilex_rp: add pci root port support for agilex platform sharath.kumar.d.m @ 2023-06-16 6:33 ` sharath.kumar.d.m 2023-06-16 15:21 ` Bjorn Helgaas ` (2 more replies) 0 siblings, 3 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-06-16 6:33 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 278 ++++++++++++++++++++++++++- 1 file changed, 268 insertions(+), 10 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 18b2361d6462..d198a73c39fe 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -18,6 +19,7 @@ #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/bitops.h> #include "../pci.h" @@ -79,9 +81,21 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define CFG_AER BIT(4) +static u32 port_conf_off; + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX */ }; struct altera_pcie { @@ -93,6 +107,7 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; }; struct altera_pcie_ops { @@ -104,6 +119,11 @@ struct altera_pcie_ops { int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, int where, int size, u32 value); + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -133,6 +153,38 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -147,6 +199,15 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -427,6 +488,126 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, int where, + int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + if (where == 0x3d) + *value = 0x01; + if (where == 0x3c) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_ep_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno << 8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) { + /* type 1 */ + switch (size) { + case 1: + cs_writeb(pcie, value, ((1 << 12) | where)); + break; + case 2: + cs_writew(pcie, value, ((1 << 12) | where)); + break; + default: + cs_writel(pcie, value, ((1 << 12) | where)); + break; + } + } else { + /* type 0 */ + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_ep_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno << 8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) { + /* type 0 */ + switch (size) { + case 1: + *value = cs_readb(pcie, ((1 << 12) | where)); + break; + case 2: + *value = cs_readw(pcie, ((1 << 12) | where)); + break; + default: + *value = cs_readl(pcie, ((1 << 12) | where)); + break; + } + } else { + /* type 0 */ + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + } + return PCIBIOS_SUCCESSFUL; +} + static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, unsigned int devfn, int where, int size, u32 *value) @@ -439,6 +620,10 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return pcie->pcie_data->ops->rp_read_cfg(pcie, where, size, value); + if (pcie->pcie_data->ops->ep_read_cfg) + return pcie->pcie_data->ops->ep_read_cfg(pcie, busno, devfn, + where, size, value); + switch (size) { case 1: byte_en = 1 << (where & 3); @@ -483,6 +668,10 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, where, size, value); + if (pcie->pcie_data->ops->ep_write_cfg) + return pcie->pcie_data->ops->ep_write_cfg(pcie, busno, devfn, + where, size, value); + switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -661,7 +850,30 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } + chained_irq_exit(chip, desc); +} +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ,\n"); + } + writel(CFG_AER, (pcie->hip_base + port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); chained_irq_exit(chip, desc); } @@ -692,11 +904,27 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &port_conf_off); + dev_info(&pcie->pdev->dev, "port_conf_stat_off =%x\n", + port_conf_off); + } + + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) @@ -708,7 +936,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -721,6 +950,7 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -729,6 +959,16 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .rp_isr = altera_pcie_isr, +}; + +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .ep_read_cfg = aglx_ep_read_cfg, + .ep_write_cfg = aglx_ep_write_cfg, + .rp_isr = aglx_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -751,11 +991,23 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, + .cfgrd0 = 0, + .cfgrd1 = 0, + .cfgwr0 = 0, + .cfgwr1 = 0, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -793,11 +1045,17 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(CFG_AER, (pcie->hip_base + port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH 1/1] pci: agilex_pci: add pcie rootport support for agilex 2023-06-16 6:33 ` [PATCH 1/1] pci: agilex_pci: add pcie rootport support for agilex sharath.kumar.d.m @ 2023-06-16 15:21 ` Bjorn Helgaas 2023-09-06 11:09 ` [PATCH v2 0/2] PCI: Altera: add support to Agilex family sharath.kumar.d.m 2023-09-11 13:45 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2 siblings, 0 replies; 56+ messages in thread From: Bjorn Helgaas @ 2023-06-16 15:21 UTC (permalink / raw) To: sharath.kumar.d.m Cc: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen, linux-kernel Thanks for your patch. If/when you revise it, run "git log --oneline drivers/pci/controller/pcie-altera.c" and match the style of subject lines, e.g., PCI: altera: Add Intel Agilex support On Fri, Jun 16, 2023 at 12:03:13PM +0530, sharath.kumar.d.m@intel.com wrote: > From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> Also, please include a commit log. Probably should also update the Kconfig help text to mention Agilex in addition to Altera. > +#include <linux/bitops.h> I don't think this is needed. > +static int aglx_rp_read_cfg(struct altera_pcie *pcie, int where, > + int size, u32 *value) > +{ > + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); > + > + switch (size) { > + case 1: > + *value = readb(addr); > + break; > + case 2: > + *value = readw(addr); > + break; > + default: > + *value = readl(addr); > + break; > + } > + > + if (where == 0x3d) > + *value = 0x01; > + if (where == 0x3c) > + *value |= 0x0100; This magic needs a comment. Apparently it works around some hardware defect? What happens if this is a single byte read? Looks like it may set more than one byte of *value. > +static int aglx_ep_write_cfg(struct altera_pcie *pcie, u8 busno, > + unsigned int devfn, int where, int size, u32 value) > +{ > + cs_writel(pcie, ((busno << 8) | devfn), AGLX_BDF_REG); > + if (busno > AGLX_RP_SECONDARY(pcie)) { > + /* type 1 */ > + switch (size) { > + case 1: > + cs_writeb(pcie, value, ((1 << 12) | where)); > + break; > + case 2: > + cs_writew(pcie, value, ((1 << 12) | where)); > + break; > + default: > + cs_writel(pcie, value, ((1 << 12) | where)); > + break; > + } > + } else { > + /* type 0 */ > + switch (size) { > + case 1: > + cs_writeb(pcie, value, where); > + break; > + case 2: > + cs_writew(pcie, value, where); > + break; > + default: > + cs_writel(pcie, value, where); > + break; > + } > + } These switches could be combined, e.g., if (busno > AGLX_RP_SECONDARY(pcie)) where |= 1 << 12; > + if (status & CFG_AER) { > + ret = generic_handle_domain_irq(pcie->irq_domain, 0); > + if (ret) > + dev_err_ratelimited(dev, "unexpected IRQ,\n"); Spurious "," at end of line. > @@ -692,11 +904,27 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) > { > struct platform_device *pdev = pcie->pdev; > > - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); > - if (IS_ERR(pcie->cra_base)) > - return PTR_ERR(pcie->cra_base); > + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || > + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { > + pcie->cra_base = > + devm_platform_ioremap_resource_byname(pdev, "Cra"); > + if (IS_ERR(pcie->cra_base)) > + return PTR_ERR(pcie->cra_base); > + } Should be a separate introductory patch since it's not directly related to Agilex. > - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { > + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { > + pcie->cs_base = > + devm_platform_ioremap_resource_byname(pdev, "Cs"); > + if (IS_ERR(pcie->cs_base)) > + return PTR_ERR(pcie->cs_base); > + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", > + &port_conf_off); > + dev_info(&pcie->pdev->dev, "port_conf_stat_off =%x\n", > + port_conf_off); > + } > + > + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || > + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { Ditto. > pcie->hip_base = > devm_platform_ioremap_resource_byname(pdev, "Hip"); > if (IS_ERR(pcie->hip_base)) > @@ -708,7 +936,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) > if (pcie->irq < 0) > return pcie->irq; > > - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); > + irq_set_chained_handler_and_data(pcie->irq, > + pcie->pcie_data->ops->rp_isr, pcie); Ditto (including the new .rp_isr initializations below). > @@ -721,6 +950,7 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { > .tlp_read_pkt = tlp_read_packet, > .tlp_write_pkt = tlp_write_packet, > .get_link_status = altera_pcie_link_up, > + .rp_isr = altera_pcie_isr, > }; > @@ -793,11 +1045,17 @@ static int altera_pcie_probe(struct platform_device *pdev) > return ret; > } > > - /* clear all interrupts */ > - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); > - /* enable all interrupts */ > - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); > - altera_pcie_host_init(pcie); > + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || > + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { > + /* clear all interrupts */ > + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); > + /* enable all interrupts */ > + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); > + altera_pcie_host_init(pcie); Ditto. > + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { > + writel(CFG_AER, (pcie->hip_base + port_conf_off > + + AGLX_ROOT_PORT_IRQ_ENABLE)); > + } > > bridge->sysdata = pcie; > bridge->busnr = pcie->root_bus_nr; > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v2 0/2] PCI: Altera: add support to Agilex family 2023-06-16 6:33 ` [PATCH 1/1] pci: agilex_pci: add pcie rootport support for agilex sharath.kumar.d.m 2023-06-16 15:21 ` Bjorn Helgaas @ 2023-09-06 11:09 ` sharath.kumar.d.m 2023-09-06 11:09 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m ` (4 more replies) 2023-09-11 13:45 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2 siblings, 5 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-06 11:09 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platform PCI: altera: add suport for Agilex Family FPGA drivers/pci/controller/pcie-altera.c | 313 ++++++++++++++++++++++++--- 1 file changed, 283 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-06 11:09 ` [PATCH v2 0/2] PCI: Altera: add support to Agilex family sharath.kumar.d.m @ 2023-09-06 11:09 ` sharath.kumar.d.m 2023-09-06 17:08 ` Bjorn Helgaas 2023-09-11 13:53 ` [PATCH v3 " sharath.kumar.d.m 2023-09-06 11:09 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA sharath.kumar.d.m ` (3 subsequent siblings) 4 siblings, 2 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-06 11:09 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 18b2361d6462..4e543ec6dfb6 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -100,10 +101,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -380,8 +386,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -400,7 +406,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -427,18 +433,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -471,18 +472,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -500,6 +496,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->ep_read_cfg) + return pcie->pcie_data->ops->ep_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->ep_write_cfg) + return pcie->pcie_data->ops->ep_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -661,7 +686,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -692,9 +716,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -708,7 +736,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -721,6 +750,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .ep_read_cfg = arr_read_cfg, + .ep_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -729,6 +763,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .ep_read_cfg = arr_read_cfg, + .ep_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -793,11 +830,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-06 11:09 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m @ 2023-09-06 17:08 ` Bjorn Helgaas 2023-09-08 9:09 ` D M, Sharath Kumar 2023-09-11 13:53 ` [PATCH v3 " sharath.kumar.d.m 1 sibling, 1 reply; 56+ messages in thread From: Bjorn Helgaas @ 2023-09-06 17:08 UTC (permalink / raw) To: sharath.kumar.d.m Cc: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen, linux-kernel Capitalize subject line to match history: PCI: altera: Refactor driver for supporting new platform On Wed, Sep 06, 2023 at 04:39:17PM +0530, sharath.kumar.d.m@intel.com wrote: > From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> Needs a commit log. It's OK to repeat the subject line. Also helpful if you can hint about why it needs to be refactored. In this case, it looks like you'll need to have a different ISR for Agilex, and also something different about root bus vs downstream config accesses. > @@ -100,10 +101,15 @@ struct altera_pcie_ops { > void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, > u32 data, bool align); > bool (*get_link_status)(struct altera_pcie *pcie); > - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, > - int size, u32 *value); > + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, > + unsigned int devfn, int where, int size, u32 *value); > int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, > - int where, int size, u32 value); > + unsigned int devfn, int where, int size, u32 value); > + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, > + unsigned int devfn, int where, int size, u32 *value); > + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, > + unsigned int devfn, int where, int size, u32 value); "ep_read_cfg" isn't the ideal name because it suggests "endpoint", but it may be either an endpoint or a switch upstream port. The rockchip driver uses "other", which isn't super descriptive either but might be better. > + void (*rp_isr)(struct irq_desc *desc); > }; > +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, > + unsigned int devfn, int where, int size, > + u32 *value) > +{ > + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) > + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, > + where, size, value); Several other drivers use pci_is_root_bus() instead of keeping track of root_bus_nr and watching for changes to it. Maybe simpler and more reliable? That would be best as a separate patch all by itself if you go that direction. > + > + if (pcie->pcie_data->ops->ep_read_cfg) > + return pcie->pcie_data->ops->ep_read_cfg(pcie, busno, devfn, > + where, size, value); > + return PCIBIOS_FUNC_NOT_SUPPORTED; > +} ^ permalink raw reply [flat|nested] 56+ messages in thread
* RE: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-06 17:08 ` Bjorn Helgaas @ 2023-09-08 9:09 ` D M, Sharath Kumar 2023-09-08 12:44 ` Bjorn Helgaas 0 siblings, 1 reply; 56+ messages in thread From: D M, Sharath Kumar @ 2023-09-08 9:09 UTC (permalink / raw) To: Bjorn Helgaas Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: Wednesday, September 6, 2023 10:38 PM > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new > platform > > Capitalize subject line to match history: > > PCI: altera: Refactor driver for supporting new platform > > On Wed, Sep 06, 2023 at 04:39:17PM +0530, sharath.kumar.d.m@intel.com > wrote: > > From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> > > Needs a commit log. It's OK to repeat the subject line. Also helpful if you can > hint about why it needs to be refactored. In this case, it looks like you'll need > to have a different ISR for Agilex, and also something different about root > bus vs downstream config accesses. > ok > > @@ -100,10 +101,15 @@ struct altera_pcie_ops { > > void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, > > u32 data, bool align); > > bool (*get_link_status)(struct altera_pcie *pcie); > > - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, > > - int size, u32 *value); > > + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, > > + unsigned int devfn, int where, int size, u32 *value); > > int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, > > - int where, int size, u32 value); > > + unsigned int devfn, int where, int size, u32 value); > > + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, > > + unsigned int devfn, int where, int size, u32 *value); > > + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, > > + unsigned int devfn, int where, int size, u32 value); > > "ep_read_cfg" isn't the ideal name because it suggests "endpoint", but it may > be either an endpoint or a switch upstream port. The rockchip driver uses > "other", which isn't super descriptive either but might be better. > Ok will change to "nonrp_read_cfg" ? > > + void (*rp_isr)(struct irq_desc *desc); > > }; > > > +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, > > + unsigned int devfn, int where, int size, > > + u32 *value) > > +{ > > + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops- > >rp_read_cfg) > > + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, > devfn, > > + where, size, value); > > Several other drivers use pci_is_root_bus() instead of keeping track of > root_bus_nr and watching for changes to it. Maybe simpler and more > reliable? That would be best as a separate patch all by itself if you go that > direction. > Will not take up as part of this commit > > + > > + if (pcie->pcie_data->ops->ep_read_cfg) > > + return pcie->pcie_data->ops->ep_read_cfg(pcie, busno, > devfn, > > + where, size, value); > > + return PCIBIOS_FUNC_NOT_SUPPORTED; > > +} ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-08 9:09 ` D M, Sharath Kumar @ 2023-09-08 12:44 ` Bjorn Helgaas 2023-09-08 13:40 ` D M, Sharath Kumar 0 siblings, 1 reply; 56+ messages in thread From: Bjorn Helgaas @ 2023-09-08 12:44 UTC (permalink / raw) To: D M, Sharath Kumar Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org On Fri, Sep 08, 2023 at 09:09:34AM +0000, D M, Sharath Kumar wrote: > > -----Original Message----- > > From: Bjorn Helgaas <helgaas@kernel.org> > > ... > > > + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, > > > + unsigned int devfn, int where, int size, u32 *value); > > > + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, > > > + unsigned int devfn, int where, int size, u32 value); > > > > "ep_read_cfg" isn't the ideal name because it suggests "endpoint", but it may > > be either an endpoint or a switch upstream port. The rockchip driver uses > > "other", which isn't super descriptive either but might be better. > > > Ok will change to "nonrp_read_cfg" ? I think the important point is not whether it's a Root Port or not, but whether it's on the root *bus* or not. In other words, I think the driver has to determine whether to generate a Type 0 (targeting something on the root bus) or a Type 1 (targeting something below a bridge) config transaction (see PCI-to-PCI Bridge spec r1.2, sec 3.1.2.1). There can be non-Root Ports on the root bus, so "nonrp" doesn't seem quite right. "Other" would be OK, since that's already used by other drivers. Maybe "type0" and "type1" would be better and would fit well with the root_bus_nr check you use to distinguish them? > > > +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, > > > + unsigned int devfn, int where, int size, > > > + u32 *value) > > > +{ > > > + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops- > > >rp_read_cfg) > > > + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, > > devfn, > > > + where, size, value); > > > + > > > + if (pcie->pcie_data->ops->ep_read_cfg) > > > + return pcie->pcie_data->ops->ep_read_cfg(pcie, busno, > > devfn, > > > + where, size, value); > > > + return PCIBIOS_FUNC_NOT_SUPPORTED; > > > +} ^ permalink raw reply [flat|nested] 56+ messages in thread
* RE: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-08 12:44 ` Bjorn Helgaas @ 2023-09-08 13:40 ` D M, Sharath Kumar 2023-09-08 19:52 ` Bjorn Helgaas 2023-09-11 20:08 ` Bjorn Helgaas 0 siblings, 2 replies; 56+ messages in thread From: D M, Sharath Kumar @ 2023-09-08 13:40 UTC (permalink / raw) To: Bjorn Helgaas Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: Friday, September 8, 2023 6:14 PM > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new > platform > > On Fri, Sep 08, 2023 at 09:09:34AM +0000, D M, Sharath Kumar wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> ... > > > > > + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, > > > > + unsigned int devfn, int where, int size, u32 *value); > > > > + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, > > > > + unsigned int devfn, int where, int size, u32 value); > > > > > > "ep_read_cfg" isn't the ideal name because it suggests "endpoint", > > > but it may be either an endpoint or a switch upstream port. The > > > rockchip driver uses "other", which isn't super descriptive either but > might be better. > > > > > Ok will change to "nonrp_read_cfg" ? > > I think the important point is not whether it's a Root Port or not, but whether > it's on the root *bus* or not. In other words, I think the driver has to > determine whether to generate a Type 0 (targeting something on the root > bus) or a Type 1 (targeting something below a > bridge) config transaction (see PCI-to-PCI Bridge spec r1.2, sec 3.1.2.1). > > There can be non-Root Ports on the root bus, so "nonrp" doesn't seem quite > right. "Other" would be OK, since that's already used by other drivers. > Maybe "type0" and "type1" would be better and would fit well with the > root_bus_nr check you use to distinguish them? > Situation is Root port configuration space - memory mapped Non root port configuration space - indirect access/proprietary access Type 0 for devices directly connected to root port Type 1 for others > > > > +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, > > > > + unsigned int devfn, int where, int size, > > > > + u32 *value) > > > > +{ > > > > + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops- > > > >rp_read_cfg) > > > > + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, > > > devfn, > > > > + where, size, value); > > > > + > > > > + if (pcie->pcie_data->ops->ep_read_cfg) > > > > + return pcie->pcie_data->ops->ep_read_cfg(pcie, busno, > > > devfn, > > > > + where, size, value); > > > > + return PCIBIOS_FUNC_NOT_SUPPORTED; } ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-08 13:40 ` D M, Sharath Kumar @ 2023-09-08 19:52 ` Bjorn Helgaas 2023-09-11 10:33 ` [PATCH 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m ` (2 more replies) 2023-09-11 20:08 ` Bjorn Helgaas 1 sibling, 3 replies; 56+ messages in thread From: Bjorn Helgaas @ 2023-09-08 19:52 UTC (permalink / raw) To: D M, Sharath Kumar Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org On Fri, Sep 08, 2023 at 01:40:13PM +0000, D M, Sharath Kumar wrote: > > -----Original Message----- > > From: Bjorn Helgaas <helgaas@kernel.org> > > On Fri, Sep 08, 2023 at 09:09:34AM +0000, D M, Sharath Kumar wrote: > > > > -----Original Message----- > > > > From: Bjorn Helgaas <helgaas@kernel.org> ... > > > > > > > + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, > > > > > + unsigned int devfn, int where, int size, u32 *value); > > > > > + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, > > > > > + unsigned int devfn, int where, int size, u32 value); > > > > > > > > "ep_read_cfg" isn't the ideal name because it suggests "endpoint", > > > > but it may be either an endpoint or a switch upstream port. The > > > > rockchip driver uses "other", which isn't super descriptive either but > > might be better. > > > > > > > Ok will change to "nonrp_read_cfg" ? > > > > I think the important point is not whether it's a Root Port or not, but whether > > it's on the root *bus* or not. In other words, I think the driver has to > > determine whether to generate a Type 0 (targeting something on the root > > bus) or a Type 1 (targeting something below a > > bridge) config transaction (see PCI-to-PCI Bridge spec r1.2, sec 3.1.2.1). > > > > There can be non-Root Ports on the root bus, so "nonrp" doesn't seem quite > > right. "Other" would be OK, since that's already used by other drivers. > > Maybe "type0" and "type1" would be better and would fit well with the > > root_bus_nr check you use to distinguish them? > > > Situation is > Root port configuration space - memory mapped > Non root port configuration space - indirect access/proprietary access > Type 0 for devices directly connected to root port > Type 1 for others "mm", "ind"? ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-08 19:52 ` Bjorn Helgaas @ 2023-09-11 10:33 ` sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:35 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform D M, Sharath Kumar 2 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 10:33 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-08 19:52 ` Bjorn Helgaas 2023-09-11 10:33 ` [PATCH 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 12:24 ` sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:35 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform D M, Sharath Kumar 2 siblings, 2 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 12:24 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-11 12:24 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 12:24 ` sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 12:24 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 2/2] PCI: altera: add support for agilex family fpga 2023-09-11 12:24 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 12:24 ` sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 12:24 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* RE: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-08 19:52 ` Bjorn Helgaas 2023-09-11 10:33 ` [PATCH 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 13:35 ` D M, Sharath Kumar 2 siblings, 0 replies; 56+ messages in thread From: D M, Sharath Kumar @ 2023-09-11 13:35 UTC (permalink / raw) To: Bjorn Helgaas Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: Saturday, September 9, 2023 1:23 AM > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new > platform > > On Fri, Sep 08, 2023 at 01:40:13PM +0000, D M, Sharath Kumar wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> On Fri, Sep 08, 2023 at > > > 09:09:34AM +0000, D M, Sharath Kumar wrote: > > > > > -----Original Message----- > > > > > From: Bjorn Helgaas <helgaas@kernel.org> ... > > > > > > > > > + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, > > > > > > + unsigned int devfn, int where, int size, u32 > *value); > > > > > > + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, > > > > > > + unsigned int devfn, int where, int size, u32 > value); > > > > > > > > > > "ep_read_cfg" isn't the ideal name because it suggests > > > > > "endpoint", but it may be either an endpoint or a switch > > > > > upstream port. The rockchip driver uses "other", which isn't > > > > > super descriptive either but > > > might be better. > > > > > > > > > Ok will change to "nonrp_read_cfg" ? > > > > > > I think the important point is not whether it's a Root Port or not, > > > but whether it's on the root *bus* or not. In other words, I think > > > the driver has to determine whether to generate a Type 0 (targeting > > > something on the root > > > bus) or a Type 1 (targeting something below a > > > bridge) config transaction (see PCI-to-PCI Bridge spec r1.2, sec 3.1.2.1). > > > > > > There can be non-Root Ports on the root bus, so "nonrp" doesn't seem > > > quite right. "Other" would be OK, since that's already used by other > drivers. > > > Maybe "type0" and "type1" would be better and would fit well with > > > the root_bus_nr check you use to distinguish them? > > > > > Situation is > > Root port configuration space - memory mapped Non root port > > configuration space - indirect access/proprietary access > > Type 0 for devices directly connected to root port > > Type 1 for others > > "mm", "ind"? Memory mapped - configuration registers available at pre defined address ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-08 13:40 ` D M, Sharath Kumar 2023-09-08 19:52 ` Bjorn Helgaas @ 2023-09-11 20:08 ` Bjorn Helgaas 2023-09-13 12:59 ` Bjorn Helgaas 1 sibling, 1 reply; 56+ messages in thread From: Bjorn Helgaas @ 2023-09-11 20:08 UTC (permalink / raw) To: D M, Sharath Kumar Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org On Fri, Sep 08, 2023 at 01:40:13PM +0000, D M, Sharath Kumar wrote: > > -----Original Message----- > > From: Bjorn Helgaas <helgaas@kernel.org> > > Sent: Friday, September 8, 2023 6:14 PM > > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > > linux-kernel@vger.kernel.org > > Subject: Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new > > platform > > > > On Fri, Sep 08, 2023 at 09:09:34AM +0000, D M, Sharath Kumar wrote: > > > > -----Original Message----- > > > > From: Bjorn Helgaas <helgaas@kernel.org> ... > > > > > > > + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, > > > > > + unsigned int devfn, int where, int size, u32 *value); > > > > > + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, > > > > > + unsigned int devfn, int where, int size, u32 value); > > > > > > > > "ep_read_cfg" isn't the ideal name because it suggests "endpoint", > > > > but it may be either an endpoint or a switch upstream port. The > > > > rockchip driver uses "other", which isn't super descriptive either but > > might be better. > > > > > > > Ok will change to "nonrp_read_cfg" ? > > > > I think the important point is not whether it's a Root Port or not, but whether > > it's on the root *bus* or not. In other words, I think the driver has to > > determine whether to generate a Type 0 (targeting something on the root > > bus) or a Type 1 (targeting something below a > > bridge) config transaction (see PCI-to-PCI Bridge spec r1.2, sec 3.1.2.1). > > > > There can be non-Root Ports on the root bus, so "nonrp" doesn't seem quite > > right. "Other" would be OK, since that's already used by other drivers. > > Maybe "type0" and "type1" would be better and would fit well with the > > root_bus_nr check you use to distinguish them? > > Situation is > Root port configuration space - memory mapped I don't quite believe the idea that the access method is based on whether it's a root port. For one thing, you decide whether to use the memory-mapped accessor or the indirect accessor based on whether the read targets the *root bus*, not whether it targets a root port. And obviously you don't *know* whether the device at a B/D/F address is a root port until after you read the PCIe type. I think using names similar to other drivers will be helpful. These all work on the root bus: exynos_pcie_rd_own_conf meson_pcie_rd_own_conf rockchip_pcie_rd_own_conf These work on non-root buses: dw_pcie_rd_other_conf rockchip_pcie_rd_other_conf > Non root port configuration space - indirect access/proprietary access > Type 0 for devices directly connected to root port > Type 1 for others > > > > > +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, > > > > > + unsigned int devfn, int where, int size, > > > > > + u32 *value) > > > > > +{ > > > > > + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops- > > > > >rp_read_cfg) > > > > > + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, > > > > devfn, > > > > > + where, size, value); > > > > > + > > > > > + if (pcie->pcie_data->ops->ep_read_cfg) > > > > > + return pcie->pcie_data->ops->ep_read_cfg(pcie, busno, > > > > devfn, > > > > > + where, size, value); > > > > > + return PCIBIOS_FUNC_NOT_SUPPORTED; } ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-11 20:08 ` Bjorn Helgaas @ 2023-09-13 12:59 ` Bjorn Helgaas 2023-09-17 17:05 ` [PATCH v4 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 0 siblings, 1 reply; 56+ messages in thread From: Bjorn Helgaas @ 2023-09-13 12:59 UTC (permalink / raw) To: D M, Sharath Kumar Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org On Mon, Sep 11, 2023 at 03:08:08PM -0500, Bjorn Helgaas wrote: > On Fri, Sep 08, 2023 at 01:40:13PM +0000, D M, Sharath Kumar wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> > > > Sent: Friday, September 8, 2023 6:14 PM > > > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > > > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > > > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > > > linux-kernel@vger.kernel.org > > > Subject: Re: [PATCH v2 1/2] PCI: altera: refactor driver for supporting new > > > platform > > > > > > On Fri, Sep 08, 2023 at 09:09:34AM +0000, D M, Sharath Kumar wrote: > > > > > -----Original Message----- > > > > > From: Bjorn Helgaas <helgaas@kernel.org> ... > > > > > > > > > + int (*ep_read_cfg)(struct altera_pcie *pcie, u8 busno, > > > > > > + unsigned int devfn, int where, int size, u32 *value); > > > > > > + int (*ep_write_cfg)(struct altera_pcie *pcie, u8 busno, > > > > > > + unsigned int devfn, int where, int size, u32 value); > > > > > > > > > > "ep_read_cfg" isn't the ideal name because it suggests "endpoint", > > > > > but it may be either an endpoint or a switch upstream port. The > > > > > rockchip driver uses "other", which isn't super descriptive either but > > > might be better. > > > > > > > > > Ok will change to "nonrp_read_cfg" ? > > > > > > I think the important point is not whether it's a Root Port or not, but whether > > > it's on the root *bus* or not. In other words, I think the driver has to > > > determine whether to generate a Type 0 (targeting something on the root > > > bus) or a Type 1 (targeting something below a > > > bridge) config transaction (see PCI-to-PCI Bridge spec r1.2, sec 3.1.2.1). > > > > > > There can be non-Root Ports on the root bus, so "nonrp" doesn't seem quite > > > right. "Other" would be OK, since that's already used by other drivers. > > > Maybe "type0" and "type1" would be better and would fit well with the > > > root_bus_nr check you use to distinguish them? > > > > Situation is > > Root port configuration space - memory mapped > > I don't quite believe the idea that the access method is based on > whether it's a root port. For one thing, you decide whether to use > the memory-mapped accessor or the indirect accessor based on whether > the read targets the *root bus*, not whether it targets a root port. > And obviously you don't *know* whether the device at a B/D/F address > is a root port until after you read the PCIe type. I see eight copies of "[PATCH v3 0/2]" on the list: https://lore.kernel.org/linux-pci/20230616063313.862996-2-sharath.kumar.d.m@intel.com/T/#t The duplication just causes confusion and slows things down. I do think the naming as root port config accessors and endpoint config accessors is fundamentally broken and needs to be fixed. It's not a *functional* issue, but it is important to avoid misleading names. > I think using names similar to other drivers will be helpful. > > These all work on the root bus: > > exynos_pcie_rd_own_conf > meson_pcie_rd_own_conf > rockchip_pcie_rd_own_conf > > These work on non-root buses: > > dw_pcie_rd_other_conf > rockchip_pcie_rd_other_conf > > > Non root port configuration space - indirect access/proprietary access > > Type 0 for devices directly connected to root port > > Type 1 for others > > > > > > > +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, > > > > > > + unsigned int devfn, int where, int size, > > > > > > + u32 *value) > > > > > > +{ > > > > > > + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops- > > > > > >rp_read_cfg) > > > > > > + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, > > > > > devfn, > > > > > > + where, size, value); > > > > > > + > > > > > > + if (pcie->pcie_data->ops->ep_read_cfg) > > > > > > + return pcie->pcie_data->ops->ep_read_cfg(pcie, busno, > > > > > devfn, > > > > > > + where, size, value); > > > > > > + return PCIBIOS_FUNC_NOT_SUPPORTED; } ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v4 0/2] PCI: altera: add support to agilex family 2023-09-13 12:59 ` Bjorn Helgaas @ 2023-09-17 17:05 ` sharath.kumar.d.m 2023-09-17 17:05 ` [PATCH v4 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m ` (2 more replies) 0 siblings, 3 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-17 17:05 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas changelog v4: added below callback for root bus alt_read/write_own_cfg added below callback for non-root buses alt_read/write_other_cfg D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platform PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 313 ++++++++++++++++++++++++--- 1 file changed, 280 insertions(+), 33 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v4 1/2] PCI: altera: refactor driver for supporting new platform 2023-09-17 17:05 ` [PATCH v4 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-17 17:05 ` sharath.kumar.d.m 2023-09-17 17:05 ` [PATCH v4 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-10-25 21:51 ` [PATCH v4 0/2] PCI: altera: add support to agilex family Bjorn Helgaas 2 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-17 17:05 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 108 +++++++++++++++++++-------- 1 file changed, 75 insertions(+), 33 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..bb073f8424ed 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); - int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + int (*alt_read_own_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*alt_write_own_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + int (*alt_read_other_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*alt_write_other_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,37 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && + pcie->pcie_data->ops->alt_read_own_cfg) + return pcie->pcie_data->ops->alt_read_own_cfg(pcie, busno, + devfn, where, size, value); + + if (pcie->pcie_data->ops->alt_read_other_cfg) + return pcie->pcie_data->ops->alt_read_other_cfg(pcie, busno, + devfn, where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && + pcie->pcie_data->ops->alt_write_own_cfg) + return pcie->pcie_data->ops->alt_write_own_cfg(pcie, busno, + devfn, where, size, value); + + if (pcie->pcie_data->ops->alt_write_other_cfg) + return pcie->pcie_data->ops->alt_write_other_cfg(pcie, busno, + devfn, where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +687,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +717,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +737,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,14 +751,22 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .alt_read_own_cfg = arr_read_cfg, + .alt_write_own_cfg = arr_write_cfg, + .alt_read_other_cfg = arr_read_cfg, + .alt_write_other_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .tlp_read_pkt = s10_tlp_read_packet, .tlp_write_pkt = s10_tlp_write_packet, .get_link_status = s10_altera_pcie_link_up, - .rp_read_cfg = s10_rp_read_cfg, - .rp_write_cfg = s10_rp_write_cfg, + .alt_read_own_cfg = s10_rp_read_cfg, + .alt_write_own_cfg = s10_rp_write_cfg, + .alt_read_other_cfg = arr_read_cfg, + .alt_write_other_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +831,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v4 2/2] PCI: altera: add support for agilex family fpga 2023-09-17 17:05 ` [PATCH v4 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-17 17:05 ` [PATCH v4 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m @ 2023-09-17 17:05 ` sharath.kumar.d.m 2023-10-25 22:05 ` Bjorn Helgaas 2023-10-25 21:51 ` [PATCH v4 0/2] PCI: altera: add support to agilex family Bjorn Helgaas 2 siblings, 1 reply; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-17 17:05 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index bb073f8424ed..46457e976615 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_read_own_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_write_own_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_write_other_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_read_other_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -690,6 +839,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -725,13 +898,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -769,6 +954,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .alt_read_own_cfg = aglx_read_own_cfg, + .alt_write_own_cfg = aglx_write_own_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .alt_read_other_cfg = aglx_read_other_cfg, + .alt_write_other_cfg = aglx_write_other_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -789,11 +983,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -838,6 +1040,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH v4 2/2] PCI: altera: add support for agilex family fpga 2023-09-17 17:05 ` [PATCH v4 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m @ 2023-10-25 22:05 ` Bjorn Helgaas 2023-10-28 13:26 ` [PATCH v5 2/2] PCI: altera: add support for agilex7 " sharath.kumar.d.m 0 siblings, 1 reply; 56+ messages in thread From: Bjorn Helgaas @ 2023-10-25 22:05 UTC (permalink / raw) To: sharath.kumar.d.m Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, Joyce Ooi [+cc Joyce] On Sun, Sep 17, 2023 at 10:35:46PM +0530, sharath.kumar.d.m@intel.com wrote: > From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> > > create new instance of struct altera_pcie_data for > "altr,pcie-root-port-3.0" > provide corresponding callback > "port_conf_off" points to avmm port config register base Please mention the hardware platform that this corresponds to. > + /* interrupt pin not programmed in hardware, set to INTA*/ Add space before closing "*/". > + if (status & AGLX_CFG_AER) { > + ret = generic_handle_domain_irq(pcie->irq_domain, 0); > + if (ret) > + dev_err_ratelimited(dev, "unexpected IRQ\n"); Maybe include a hint about what the unexpected IRQ was? An IRQ number or "status" value? > +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { > + .alt_read_own_cfg = aglx_read_own_cfg, > + .alt_write_own_cfg = aglx_write_own_cfg, > + .get_link_status = aglx_altera_pcie_link_up, > + .alt_read_other_cfg = aglx_read_other_cfg, > + .alt_write_other_cfg = aglx_write_other_cfg, > + .rp_isr = aglx_isr, Use the same order of function pointers in all of these structs and make it match the struct altera_pcie_ops definition. (Don't put .get_link_status in the middle of the config accessors.) > static const struct of_device_id altera_pcie_of_match[] = { > {.compatible = "altr,pcie-root-port-1.0", > .data = &altera_pcie_1_0_data }, > {.compatible = "altr,pcie-root-port-2.0", > .data = &altera_pcie_2_0_data }, > + {.compatible = "altr,pcie-root-port-3.0", > + .data = &altera_pcie_3_0_data }, Make the .data indentation match the rest. ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v5 2/2] PCI: altera: add support for agilex7 family fpga 2023-10-25 22:05 ` Bjorn Helgaas @ 2023-10-28 13:26 ` sharath.kumar.d.m 0 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-10-28 13:26 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, joyce.ooi, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for agilex7 "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index bb073f8424ed..56ee27d54de0 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_read_own_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA */ + if (where == PCI_INTERRUPT_PIN && size == 1 && !(*value)) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE && !(*value & 0xff00)) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_write_own_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_write_other_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_read_other_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -690,6 +839,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ %x\n", status); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -725,13 +898,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -769,6 +954,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .get_link_status = aglx_altera_pcie_link_up, + .alt_read_own_cfg = aglx_read_own_cfg, + .alt_write_own_cfg = aglx_write_own_cfg, + .alt_read_other_cfg = aglx_read_other_cfg, + .alt_write_other_cfg = aglx_write_other_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -789,11 +983,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", /* agilex7 P,F tile */ + .data = &altera_pcie_3_0_data }, {}, }; @@ -838,6 +1040,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH v4 0/2] PCI: altera: add support to agilex family 2023-09-17 17:05 ` [PATCH v4 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-17 17:05 ` [PATCH v4 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m 2023-09-17 17:05 ` [PATCH v4 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m @ 2023-10-25 21:51 ` Bjorn Helgaas 2023-10-28 13:33 ` [PATCH v5 " sharath.kumar.d.m 2 siblings, 1 reply; 56+ messages in thread From: Bjorn Helgaas @ 2023-10-25 21:51 UTC (permalink / raw) To: sharath.kumar.d.m, Joyce Ooi Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh [+to Joyce, Altera PCIe maintainer] On Sun, Sep 17, 2023 at 10:35:44PM +0530, sharath.kumar.d.m@intel.com wrote: > From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> > > added new callback for > 1) read,write to root port configuration registers > 2) read,write to endpoint configuration registers > 3) root port interrupt handler > > agilex and newer platforms need to implemant the callback and generic root > port driver should work ( without much changes ) , legacy platforms (arria > and startix) implement configuration read,write directly in wrapper > api _altera_pcie_cfg_read/_altera_pcie_cfg_write Do these patches make the driver work on some new platform? Has it been tested? Please include the name of the new platform. Saying this "... driver should work (without much changes)" does not sound like anything has actually been tested on hardware. > changelog v2: > saperated into two patches > 1.refactored the driver for easily portability to future Altera FPGA > platforms > 2.added support for "Agilex" FPGA > > this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up > to the user to add PCI RP or not ( as per his needs). we are not adding > the device tree as part of this commit. we are expecting the add device > tree changes only if he is adding PCI RP IP in his design Please cc: Joyce on any future postings, since she's listed as the maintainer for pcie-altera.c. Joyce, please comment on these. We don't like to merge things affecting your file unless you approve. > changelog v3: > incorporate review comments from Bjorn Helgaas > > changelog v4: > added below callback for root bus > alt_read/write_own_cfg > added below callback for non-root buses > alt_read/write_other_cfg > > D M Sharath Kumar (2): > PCI: altera: refactor driver for supporting new platform > PCI: altera: add support for agilex family fpga > > drivers/pci/controller/pcie-altera.c | 313 ++++++++++++++++++++++++--- > 1 file changed, 280 insertions(+), 33 deletions(-) > > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v5 0/2] PCI: altera: add support to agilex family 2023-10-25 21:51 ` [PATCH v4 0/2] PCI: altera: add support to agilex family Bjorn Helgaas @ 2023-10-28 13:33 ` sharath.kumar.d.m 0 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-10-28 13:33 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, joyce.ooi, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas changelog v4: added below callback for root bus alt_read/write_own_cfg added below callback for non-root buses alt_read/write_other_cfg changelog v5 the driver is tested on agilex7 and information is below https://www.rocketboards.org/foswiki/Documentation/Agilex7PCIeRootPortDesign incorporate review comments from Bjorn Helgaas added comments on the supported family {.compatible = "altr,pcie-root-port-3.0", /* agilex7 P,F tile */ printing the satus dev_err_ratelimited(dev, "unexpected IRQ %x\n", status); indentation etc D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platform PCI: altera: add support for agilex7 family fpga drivers/pci/controller/pcie-altera.c | 313 ++++++++++++++++++++++++--- 1 file changed, 280 insertions(+), 33 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-06 11:09 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m 2023-09-06 17:08 ` Bjorn Helgaas @ 2023-09-11 13:53 ` sharath.kumar.d.m 2023-09-11 13:53 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m ` (2 more replies) 1 sibling, 3 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:53 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-11 13:53 ` [PATCH v3 " sharath.kumar.d.m @ 2023-09-11 13:53 ` sharath.kumar.d.m 2023-09-11 13:53 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-15 10:51 ` [PATCH v3 0/2] PCI: altera: add support to agilex family Dinh Nguyen 2 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:53 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 2/2] PCI: altera: add support for agilex family fpga 2023-09-11 13:53 ` [PATCH v3 " sharath.kumar.d.m 2023-09-11 13:53 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 13:53 ` sharath.kumar.d.m 2023-09-15 10:51 ` [PATCH v3 0/2] PCI: altera: add support to agilex family Dinh Nguyen 2 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:53 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-11 13:53 ` [PATCH v3 " sharath.kumar.d.m 2023-09-11 13:53 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:53 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m @ 2023-09-15 10:51 ` Dinh Nguyen 2 siblings, 0 replies; 56+ messages in thread From: Dinh Nguyen @ 2023-09-15 10:51 UTC (permalink / raw) To: sharath.kumar.d.m, lpieralisi, kw, robh, bhelgaas, linux-pci; +Cc: linux-kernel On 9/11/23 08:53, sharath.kumar.d.m@intel.com wrote: > From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> > > added new callback for > 1) read,write to root port configuration registers > 2) read,write to endpoint configuration registers > 3) root port interrupt handler > > agilex and newer platforms need to implemant the callback and generic root > port driver should work ( without much changes ) , legacy platforms (arria > and startix) implement configuration read,write directly in wrapper > api _altera_pcie_cfg_read/_altera_pcie_cfg_write > > changelog v2: > saperated into two patches > 1.refactored the driver for easily portability to future Altera FPGA > platforms > 2.added support for "Agilex" FPGA > > this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up > to the user to add PCI RP or not ( as per his needs). we are not adding > the device tree as part of this commit. we are expecting the add device > tree changes only if he is adding PCI RP IP in his design > > changelog v3: > incorporate review comments from Bjorn Helgaas > > You've sent 6 versions of this patchset in a 3-hour time span, what is going on? Dinh ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA 2023-09-06 11:09 ` [PATCH v2 0/2] PCI: Altera: add support to Agilex family sharath.kumar.d.m 2023-09-06 11:09 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m @ 2023-09-06 11:09 ` sharath.kumar.d.m 2023-09-06 17:12 ` Bjorn Helgaas ` (3 more replies) 2023-09-11 10:15 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m ` (2 subsequent siblings) 4 siblings, 4 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-06 11:09 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 215 ++++++++++++++++++++++++++- 1 file changed, 214 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 4e543ec6dfb6..bc040a992eb9 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -80,9 +80,21 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define CFG_AER (1<<4) +static u32 port_conf_off; + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -94,6 +106,7 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; }; struct altera_pcie_ops { @@ -139,6 +152,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -153,6 +199,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -433,6 +487,106 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware + */ + if (where == 0x3d) + *value = 0x01; + if (where == 0x3c) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_ep_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) { + /* type 1 */ + where |= (1<<12); + } + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_ep_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) { + /* type 1 */ + where |= (1<<12); + } + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -689,6 +843,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ,\n"); + } + writel(CFG_AER, (pcie->hip_base + port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -724,13 +902,24 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &port_conf_off); + dev_info(&pcie->pdev->dev, "port_conf_stat_off =%x\n", port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -768,6 +957,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .ep_read_cfg = aglx_ep_read_cfg, + .ep_write_cfg = aglx_ep_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -788,11 +986,23 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, + .cfgrd0 = 0, + .cfgrd1 = 0, + .cfgwr0 = 0, + .cfgwr1 = 0, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -837,6 +1047,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(CFG_AER, (pcie->hip_base + port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA 2023-09-06 11:09 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA sharath.kumar.d.m @ 2023-09-06 17:12 ` Bjorn Helgaas 2023-09-08 9:15 ` D M, Sharath Kumar 2023-09-11 13:16 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m ` (2 subsequent siblings) 3 siblings, 1 reply; 56+ messages in thread From: Bjorn Helgaas @ 2023-09-06 17:12 UTC (permalink / raw) To: sharath.kumar.d.m Cc: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen, linux-kernel Capitalize subject line similarly. s/suport/support/ On Wed, Sep 06, 2023 at 04:39:18PM +0530, sharath.kumar.d.m@intel.com wrote: > From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> Needs a commit log. It's ok to repeat the subject line. > +#define AGLX_BDF_REG 0x00002004 > +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c > +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 > +#define CFG_AER (1<<4) This seems to be AGLX-specific so maybe should have a prefix? > +static u32 port_conf_off; port_conf_off looks like something that should be per-controller. > +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, > + int where, int size, u32 *value) > +{ > + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); > + > + switch (size) { > + case 1: > + *value = readb(addr); > + break; > + case 2: > + *value = readw(addr); > + break; > + default: > + *value = readl(addr); > + break; > + } > + > + /* interrupt pin not programmed in hardware > + */ Use single-line comment style: /* interrupt pin not programmed in hardware */ > + if (where == 0x3d) > + *value = 0x01; > + if (where == 0x3c) > + *value |= 0x0100; Use PCI_INTERRUPT_LINE and PCI_INTERRUPT_PIN. > + return PCIBIOS_SUCCESSFUL; > +} > +static void aglx_isr(struct irq_desc *desc) > +{ > + struct irq_chip *chip = irq_desc_get_chip(desc); > + struct altera_pcie *pcie; > + struct device *dev; > + u32 status; > + int ret; > + > + chained_irq_enter(chip, desc); > + pcie = irq_desc_get_handler_data(desc); > + dev = &pcie->pdev->dev; > + > + status = readl((pcie->hip_base + port_conf_off > + + AGLX_ROOT_PORT_IRQ_STATUS)); > + if (status & CFG_AER) { > + ret = generic_handle_domain_irq(pcie->irq_domain, 0); > + if (ret) > + dev_err_ratelimited(dev, "unexpected IRQ,\n"); Remove the comma at end (or maybe you meant to add something else?) Looks like the place it was copied from had "unexpected IRQ, INT%d". > + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { > + pcie->cs_base = > + devm_platform_ioremap_resource_byname(pdev, "Cs"); > + if (IS_ERR(pcie->cs_base)) > + return PTR_ERR(pcie->cs_base); > + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", > + &port_conf_off); > + dev_info(&pcie->pdev->dev, "port_conf_stat_off =%x\n", port_conf_off); Is this a debug message? Doesn't look like something we need all the time. If you want it all the time, use %#x so it's clear that it's hex. > +static const struct altera_pcie_data altera_pcie_3_0_data = { > + .ops = &altera_pcie_ops_3_0, > + .version = ALTERA_PCIE_V3, > + .cap_offset = 0x70, > + .cfgrd0 = 0, > + .cfgrd1 = 0, > + .cfgwr0 = 0, > + .cfgwr1 = 0, cfgrd0, ..., cfgwr1 aren't used here, so no need to initialize them. ^ permalink raw reply [flat|nested] 56+ messages in thread
* RE: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA 2023-09-06 17:12 ` Bjorn Helgaas @ 2023-09-08 9:15 ` D M, Sharath Kumar 2023-09-08 12:47 ` Bjorn Helgaas 0 siblings, 1 reply; 56+ messages in thread From: D M, Sharath Kumar @ 2023-09-08 9:15 UTC (permalink / raw) To: Bjorn Helgaas Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: Wednesday, September 6, 2023 10:42 PM > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA > > Capitalize subject line similarly. ok > > s/suport/support/ ok > > On Wed, Sep 06, 2023 at 04:39:18PM +0530, sharath.kumar.d.m@intel.com > wrote: > > From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> > > Needs a commit log. It's ok to repeat the subject line. ok > > > +#define AGLX_BDF_REG 0x00002004 > > +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c #define > > +AGLX_ROOT_PORT_IRQ_ENABLE 0x150 > > +#define CFG_AER (1<<4) > > This seems to be AGLX-specific so maybe should have a prefix? Will change to AGLX_CFG_AER > > > +static u32 port_conf_off; > > port_conf_off looks like something that should be per-controller. Specific to agilex, will rename to "aglx_port_conf_off" > > > +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, > > + int where, int size, u32 *value) > > +{ > > + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); > > + > > + switch (size) { > > + case 1: > > + *value = readb(addr); > > + break; > > + case 2: > > + *value = readw(addr); > > + break; > > + default: > > + *value = readl(addr); > > + break; > > + } > > + > > + /* interrupt pin not programmed in hardware > > + */ > > Use single-line comment style: ok > > /* interrupt pin not programmed in hardware */ > > > + if (where == 0x3d) > > + *value = 0x01; > > + if (where == 0x3c) > > + *value |= 0x0100; > > Use PCI_INTERRUPT_LINE and PCI_INTERRUPT_PIN. ok > > > + return PCIBIOS_SUCCESSFUL; > > +} > > > +static void aglx_isr(struct irq_desc *desc) { > > + struct irq_chip *chip = irq_desc_get_chip(desc); > > + struct altera_pcie *pcie; > > + struct device *dev; > > + u32 status; > > + int ret; > > + > > + chained_irq_enter(chip, desc); > > + pcie = irq_desc_get_handler_data(desc); > > + dev = &pcie->pdev->dev; > > + > > + status = readl((pcie->hip_base + port_conf_off > > + + AGLX_ROOT_PORT_IRQ_STATUS)); > > + if (status & CFG_AER) { > > + ret = generic_handle_domain_irq(pcie->irq_domain, 0); > > + if (ret) > > + dev_err_ratelimited(dev, "unexpected IRQ,\n"); > > Remove the comma at end (or maybe you meant to add something else?) > Looks like the place it was copied from had "unexpected IRQ, INT%d". ok > > > + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { > > + pcie->cs_base = > > + devm_platform_ioremap_resource_byname(pdev, > "Cs"); > > + if (IS_ERR(pcie->cs_base)) > > + return PTR_ERR(pcie->cs_base); > > + of_property_read_u32(pcie->pdev->dev.of_node, > "port_conf_stat", > > + &port_conf_off); > > + dev_info(&pcie->pdev->dev, "port_conf_stat_off =%x\n", > > +port_conf_off); > > Is this a debug message? Doesn't look like something we need all the time. If > you want it all the time, use %#x so it's clear that it's hex. ok > > > +static const struct altera_pcie_data altera_pcie_3_0_data = { > > + .ops = &altera_pcie_ops_3_0, > > + .version = ALTERA_PCIE_V3, > > + .cap_offset = 0x70, > > > + .cfgrd0 = 0, > > + .cfgrd1 = 0, > > + .cfgwr0 = 0, > > + .cfgwr1 = 0, > > cfgrd0, ..., cfgwr1 aren't used here, so no need to initialize them. ok ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA 2023-09-08 9:15 ` D M, Sharath Kumar @ 2023-09-08 12:47 ` Bjorn Helgaas 2023-09-08 14:35 ` D M, Sharath Kumar 0 siblings, 1 reply; 56+ messages in thread From: Bjorn Helgaas @ 2023-09-08 12:47 UTC (permalink / raw) To: D M, Sharath Kumar Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org On Fri, Sep 08, 2023 at 09:15:09AM +0000, D M, Sharath Kumar wrote: > > -----Original Message----- > > From: Bjorn Helgaas <helgaas@kernel.org> > > > +static u32 port_conf_off; > > > > port_conf_off looks like something that should be per-controller. > Specific to agilex, will rename to "aglx_port_conf_off" This comment was not about the *name*, it was about the fact that it's a single instance that applies to *all* controllers. It might be the case that current hardware only supports a single controller, or that if you have multiple controllers they all use the same port_conf_off value, but for generality, values like this would normally be in the per-controller structure. Bjorn ^ permalink raw reply [flat|nested] 56+ messages in thread
* RE: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA 2023-09-08 12:47 ` Bjorn Helgaas @ 2023-09-08 14:35 ` D M, Sharath Kumar 2023-09-08 19:48 ` Bjorn Helgaas 0 siblings, 1 reply; 56+ messages in thread From: D M, Sharath Kumar @ 2023-09-08 14:35 UTC (permalink / raw) To: Bjorn Helgaas Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: Friday, September 8, 2023 6:17 PM > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA > > On Fri, Sep 08, 2023 at 09:15:09AM +0000, D M, Sharath Kumar wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> > > > > > +static u32 port_conf_off; > > > > > > port_conf_off looks like something that should be per-controller. > > Specific to agilex, will rename to "aglx_port_conf_off" > > This comment was not about the *name*, it was about the fact that it's a > single instance that applies to *all* controllers. It might be the case that > current hardware only supports a single controller, or that if you have > multiple controllers they all use the same port_conf_off value, but for > generality, values like this would normally be in the per-controller structure. > > Bjorn This driver supports 3 controllers/family ( arria, startix, agilex ) This variable is only for agilex What is ur suggestion ? To add in controller data structure (struct altera_pcie_data) ? ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA 2023-09-08 14:35 ` D M, Sharath Kumar @ 2023-09-08 19:48 ` Bjorn Helgaas 2023-09-11 10:38 ` [PATCH 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m ` (2 more replies) 0 siblings, 3 replies; 56+ messages in thread From: Bjorn Helgaas @ 2023-09-08 19:48 UTC (permalink / raw) To: D M, Sharath Kumar Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org On Fri, Sep 08, 2023 at 02:35:29PM +0000, D M, Sharath Kumar wrote: > > -----Original Message----- > > From: Bjorn Helgaas <helgaas@kernel.org> > > Sent: Friday, September 8, 2023 6:17 PM > > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > > linux-kernel@vger.kernel.org > > Subject: Re: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA > > > > On Fri, Sep 08, 2023 at 09:15:09AM +0000, D M, Sharath Kumar wrote: > > > > -----Original Message----- > > > > From: Bjorn Helgaas <helgaas@kernel.org> > > > > > > > +static u32 port_conf_off; > > > > > > > > port_conf_off looks like something that should be per-controller. > > > Specific to agilex, will rename to "aglx_port_conf_off" > > > > This comment was not about the *name*, it was about the fact that it's a > > single instance that applies to *all* controllers. It might be the case that > > current hardware only supports a single controller, or that if you have > > multiple controllers they all use the same port_conf_off value, but for > > generality, values like this would normally be in the per-controller structure. > > This driver supports 3 controllers/family ( arria, startix, agilex ) > This variable is only for agilex > What is ur suggestion ? > To add in controller data structure (struct altera_pcie_data) ? That seems like a logical place. ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 2/2] PCI: altera: add support for agilex family fpga 2023-09-08 19:48 ` Bjorn Helgaas @ 2023-09-11 10:38 ` sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 14:08 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA D M, Sharath Kumar 2 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 10:38 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-08 19:48 ` Bjorn Helgaas 2023-09-11 10:38 ` [PATCH 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m @ 2023-09-11 13:08 ` sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 14:08 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA D M, Sharath Kumar 2 siblings, 2 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:08 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-11 13:08 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 13:08 ` sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:08 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 2/2] PCI: altera: add support for agilex family fpga 2023-09-11 13:08 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 13:08 ` sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:08 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* RE: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA 2023-09-08 19:48 ` Bjorn Helgaas 2023-09-11 10:38 ` [PATCH 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 14:08 ` D M, Sharath Kumar 2 siblings, 0 replies; 56+ messages in thread From: D M, Sharath Kumar @ 2023-09-11 14:08 UTC (permalink / raw) To: Bjorn Helgaas Cc: lpieralisi@kernel.org, kw@linux.com, robh@kernel.org, bhelgaas@google.com, linux-pci@vger.kernel.org, dinguyen@kernel.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: Saturday, September 9, 2023 1:19 AM > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA > > On Fri, Sep 08, 2023 at 02:35:29PM +0000, D M, Sharath Kumar wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> > > > Sent: Friday, September 8, 2023 6:17 PM > > > To: D M, Sharath Kumar <sharath.kumar.d.m@intel.com> > > > Cc: lpieralisi@kernel.org; kw@linux.com; robh@kernel.org; > > > bhelgaas@google.com; linux-pci@vger.kernel.org; dinguyen@kernel.org; > > > linux-kernel@vger.kernel.org > > > Subject: Re: [PATCH v2 2/2] PCI: altera: add suport for Agilex > > > Family FPGA > > > > > > On Fri, Sep 08, 2023 at 09:15:09AM +0000, D M, Sharath Kumar wrote: > > > > > -----Original Message----- > > > > > From: Bjorn Helgaas <helgaas@kernel.org> > > > > > > > > > +static u32 port_conf_off; > > > > > > > > > > port_conf_off looks like something that should be per-controller. > > > > Specific to agilex, will rename to "aglx_port_conf_off" > > > > > > This comment was not about the *name*, it was about the fact that > > > it's a single instance that applies to *all* controllers. It might > > > be the case that current hardware only supports a single controller, > > > or that if you have multiple controllers they all use the same > > > port_conf_off value, but for generality, values like this would normally be > in the per-controller structure. > > > > This driver supports 3 controllers/family ( arria, startix, agilex ) > > This variable is only for agilex What is ur suggestion ? > > To add in controller data structure (struct altera_pcie_data) ? > > That seems like a logical place. ok ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-06 11:09 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA sharath.kumar.d.m 2023-09-06 17:12 ` Bjorn Helgaas @ 2023-09-11 13:16 ` sharath.kumar.d.m 2023-09-11 13:16 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:16 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:22 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 3 siblings, 2 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:16 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-11 13:16 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 13:16 ` sharath.kumar.d.m 2023-09-11 13:16 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:16 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 2/2] PCI: altera: add support for agilex family fpga 2023-09-11 13:16 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:16 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 13:16 ` sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:16 UTC (permalink / raw) To: helgaas Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh, sharath.kumar.d.m From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-06 11:09 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA sharath.kumar.d.m 2023-09-06 17:12 ` Bjorn Helgaas 2023-09-11 13:16 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 13:22 ` sharath.kumar.d.m 2023-09-11 13:22 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:22 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 3 siblings, 2 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:22 UTC (permalink / raw) To: helgaas Cc: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen, linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-11 13:22 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 13:22 ` sharath.kumar.d.m 2023-09-11 13:22 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:22 UTC (permalink / raw) To: helgaas Cc: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen, linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 2/2] PCI: altera: add support for agilex family fpga 2023-09-11 13:22 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:22 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 13:22 ` sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:22 UTC (permalink / raw) To: helgaas Cc: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen, linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-06 11:09 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA sharath.kumar.d.m ` (2 preceding siblings ...) 2023-09-11 13:22 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 13:25 ` sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 3 siblings, 2 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:25 UTC (permalink / raw) To: helgaas, linux-pci, linux-kernel Cc: lpieralisi, kw, robh, bhelgaas, dinguyen, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-11 13:25 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 13:25 ` sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:25 UTC (permalink / raw) To: helgaas, linux-pci, linux-kernel Cc: lpieralisi, kw, robh, bhelgaas, dinguyen, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 2/2] PCI: altera: add support for agilex family fpga 2023-09-11 13:25 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 13:25 ` sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:25 UTC (permalink / raw) To: helgaas, linux-pci, linux-kernel Cc: lpieralisi, kw, robh, bhelgaas, dinguyen, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-06 11:09 ` [PATCH v2 0/2] PCI: Altera: add support to Agilex family sharath.kumar.d.m 2023-09-06 11:09 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m 2023-09-06 11:09 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA sharath.kumar.d.m @ 2023-09-11 10:15 ` sharath.kumar.d.m 2023-09-11 12:16 ` sharath.kumar.d.m 2023-09-11 13:31 ` sharath.kumar.d.m 4 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 10:15 UTC (permalink / raw) To: sharath.kumar.d.m Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-06 11:09 ` [PATCH v2 0/2] PCI: Altera: add support to Agilex family sharath.kumar.d.m ` (2 preceding siblings ...) 2023-09-11 10:15 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 12:16 ` sharath.kumar.d.m 2023-09-11 13:31 ` sharath.kumar.d.m 4 siblings, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 12:16 UTC (permalink / raw) To: sharath.kumar.d.m Cc: bhelgaas, dinguyen, kw, linux-kernel, linux-pci, lpieralisi, robh From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-09-06 11:09 ` [PATCH v2 0/2] PCI: Altera: add support to Agilex family sharath.kumar.d.m ` (3 preceding siblings ...) 2023-09-11 12:16 ` sharath.kumar.d.m @ 2023-09-11 13:31 ` sharath.kumar.d.m 2023-09-11 13:31 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:31 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 4 siblings, 2 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:31 UTC (permalink / raw) To: helgaas, linux-pci, linux-kernel Cc: lpieralisi, kw, robh, bhelgaas, dinguyen, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-11 13:31 ` sharath.kumar.d.m @ 2023-09-11 13:31 ` sharath.kumar.d.m 2023-09-11 13:31 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:31 UTC (permalink / raw) To: helgaas, linux-pci, linux-kernel Cc: lpieralisi, kw, robh, bhelgaas, dinguyen, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 2/2] PCI: altera: add support for agilex family fpga 2023-09-11 13:31 ` sharath.kumar.d.m 2023-09-11 13:31 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 13:31 ` sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:31 UTC (permalink / raw) To: helgaas, linux-pci, linux-kernel Cc: lpieralisi, kw, robh, bhelgaas, dinguyen, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 0/2] PCI: altera: add support to agilex family 2023-06-16 6:33 ` [PATCH 1/1] pci: agilex_pci: add pcie rootport support for agilex sharath.kumar.d.m 2023-06-16 15:21 ` Bjorn Helgaas 2023-09-06 11:09 ` [PATCH v2 0/2] PCI: Altera: add support to Agilex family sharath.kumar.d.m @ 2023-09-11 13:45 ` sharath.kumar.d.m 2023-09-11 13:45 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:45 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2 siblings, 2 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:45 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added new callback for 1) read,write to root port configuration registers 2) read,write to endpoint configuration registers 3) root port interrupt handler agilex and newer platforms need to implemant the callback and generic root port driver should work ( without much changes ) , legacy platforms (arria and startix) implement configuration read,write directly in wrapper api _altera_pcie_cfg_read/_altera_pcie_cfg_write changelog v2: saperated into two patches 1.refactored the driver for easily portability to future Altera FPGA platforms 2.added support for "Agilex" FPGA this driver supports PCI RP IP on Agilex FPGA, as these are FPGA its up to the user to add PCI RP or not ( as per his needs). we are not adding the device tree as part of this commit. we are expecting the add device tree changes only if he is adding PCI RP IP in his design changelog v3: incorporate review comments from Bjorn Helgaas D M Sharath Kumar (2): PCI: altera: refactor driver for supporting new platforms PCI: altera: add support for agilex family fpga drivers/pci/controller/pcie-altera.c | 305 ++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms 2023-09-11 13:45 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m @ 2023-09-11 13:45 ` sharath.kumar.d.m 2023-09-11 13:45 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:45 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> added the below callbacks that eases is supporting newer platforms for read/write to root port configuration space registers for read/write to non root port (endpoint, switch) cfg space regs root port interrupt handler Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 100 +++++++++++++++++++-------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..878f86b1cc6b 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -3,6 +3,7 @@ * Copyright Altera Corporation (C) 2013-2015. All rights reserved * * Author: Ley Foon Tan <lftan@altera.com> + * Author: sharath <sharath.kumar.d.m@intel.com> * Description: Altera PCIe host controller driver */ @@ -99,10 +100,15 @@ struct altera_pcie_ops { void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, u32 data, bool align); bool (*get_link_status)(struct altera_pcie *pcie); - int (*rp_read_cfg)(struct altera_pcie *pcie, int where, - int size, u32 *value); + int (*rp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, - int where, int size, u32 value); + unsigned int devfn, int where, int size, u32 value); + int (*nonrp_read_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value); + int (*nonrp_write_cfg)(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value); + void (*rp_isr)(struct irq_desc *desc); }; struct altera_pcie_data { @@ -379,8 +385,8 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, - int size, u32 *value) +static int s10_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -399,7 +405,7 @@ static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, return PCIBIOS_SUCCESSFUL; } -static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, +static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 value) { void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); @@ -426,18 +432,13 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 *value) +static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) { int ret; u32 data; u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) - return pcie->pcie_data->ops->rp_read_cfg(pcie, where, - size, value); - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -470,18 +471,13 @@ static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, return PCIBIOS_SUCCESSFUL; } -static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, - unsigned int devfn, int where, int size, - u32 value) +static int arr_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) { u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) - return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, - where, size, value); - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -499,6 +495,35 @@ static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, data32); + +} + +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) + return pcie->pcie_data->ops->rp_read_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_read_cfg) + return pcie->pcie_data->ops->nonrp_read_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) +{ + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, devfn, + where, size, value); + + if (pcie->pcie_data->ops->nonrp_write_cfg) + return pcie->pcie_data->ops->nonrp_write_cfg(pcie, busno, devfn, + where, size, value); + return PCIBIOS_FUNC_NOT_SUPPORTED; } static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, @@ -660,7 +685,6 @@ static void altera_pcie_isr(struct irq_desc *desc) dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n", bit); } } - chained_irq_exit(chip, desc); } @@ -691,9 +715,13 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) { struct platform_device *pdev = pcie->pdev; - pcie->cra_base = devm_platform_ioremap_resource_byname(pdev, "Cra"); - if (IS_ERR(pcie->cra_base)) - return PTR_ERR(pcie->cra_base); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + pcie->cra_base = + devm_platform_ioremap_resource_byname(pdev, "Cra"); + if (IS_ERR(pcie->cra_base)) + return PTR_ERR(pcie->cra_base); + } if (pcie->pcie_data->version == ALTERA_PCIE_V2) { pcie->hip_base = @@ -707,7 +735,8 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) if (pcie->irq < 0) return pcie->irq; - irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + irq_set_chained_handler_and_data(pcie->irq, + pcie->pcie_data->ops->rp_isr, pcie); return 0; } @@ -720,6 +749,11 @@ static const struct altera_pcie_ops altera_pcie_ops_1_0 = { .tlp_read_pkt = tlp_read_packet, .tlp_write_pkt = tlp_write_packet, .get_link_status = altera_pcie_link_up, + .rp_read_cfg = arr_read_cfg, + .rp_write_cfg = arr_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_ops altera_pcie_ops_2_0 = { @@ -728,6 +762,9 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .get_link_status = s10_altera_pcie_link_up, .rp_read_cfg = s10_rp_read_cfg, .rp_write_cfg = s10_rp_write_cfg, + .nonrp_read_cfg = arr_read_cfg, + .nonrp_write_cfg = arr_write_cfg, + .rp_isr = altera_pcie_isr, }; static const struct altera_pcie_data altera_pcie_1_0_data = { @@ -792,11 +829,14 @@ static int altera_pcie_probe(struct platform_device *pdev) return ret; } - /* clear all interrupts */ - cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); - /* enable all interrupts */ - cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); - altera_pcie_host_init(pcie); + if ((pcie->pcie_data->version == ALTERA_PCIE_V1) || + (pcie->pcie_data->version == ALTERA_PCIE_V2)) { + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ + cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + } bridge->sysdata = pcie; bridge->busnr = pcie->root_bus_nr; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH v3 2/2] PCI: altera: add support for agilex family fpga 2023-09-11 13:45 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:45 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m @ 2023-09-11 13:45 ` sharath.kumar.d.m 1 sibling, 0 replies; 56+ messages in thread From: sharath.kumar.d.m @ 2023-09-11 13:45 UTC (permalink / raw) To: lpieralisi, kw, robh, bhelgaas, linux-pci, dinguyen Cc: linux-kernel, D M Sharath Kumar From: D M Sharath Kumar <sharath.kumar.d.m@intel.com> create new instance of struct altera_pcie_data for "altr,pcie-root-port-3.0" provide corresponding callback "port_conf_off" points to avmm port config register base Signed-off-by: D M Sharath Kumar <sharath.kumar.d.m@intel.com> --- drivers/pci/controller/pcie-altera.c | 207 ++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 878f86b1cc6b..aa14ea588487 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -79,9 +79,20 @@ #define S10_TLP_FMTTYPE_CFGWR0 0x45 #define S10_TLP_FMTTYPE_CFGWR1 0x44 +#define AGLX_RP_CFG_ADDR(pcie, reg) \ + (((pcie)->hip_base) + (reg)) +#define AGLX_RP_SECONDARY(pcie) \ + readb(AGLX_RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) + +#define AGLX_BDF_REG 0x00002004 +#define AGLX_ROOT_PORT_IRQ_STATUS 0x14c +#define AGLX_ROOT_PORT_IRQ_ENABLE 0x150 +#define AGLX_CFG_AER (1<<4) + enum altera_pcie_version { ALTERA_PCIE_V1 = 0, ALTERA_PCIE_V2, + ALTERA_PCIE_V3, /* AGILEX p-tile, f-tile */ }; struct altera_pcie { @@ -93,6 +104,8 @@ struct altera_pcie { struct irq_domain *irq_domain; struct resource bus_range; const struct altera_pcie_data *pcie_data; + void __iomem *cs_base; + u32 port_conf_off; }; struct altera_pcie_ops { @@ -138,6 +151,39 @@ static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) return readl_relaxed(pcie->cra_base + reg); } +static inline void cs_writel(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writel_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writew(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writew_relaxed(value, pcie->cs_base + reg); +} + +static inline void cs_writeb(struct altera_pcie *pcie, const u32 value, + const u32 reg) +{ + writeb_relaxed(value, pcie->cs_base + reg); +} + +static inline u32 cs_readl(struct altera_pcie *pcie, const u32 reg) +{ + return readl_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readw(struct altera_pcie *pcie, const u32 reg) +{ + return readw_relaxed(pcie->cs_base + reg); +} + +static inline u32 cs_readb(struct altera_pcie *pcie, const u32 reg) +{ + return readb_relaxed(pcie->cs_base + reg); +} + static bool altera_pcie_link_up(struct altera_pcie *pcie) { return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); @@ -152,6 +198,14 @@ static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); } +static bool aglx_altera_pcie_link_up(struct altera_pcie *pcie) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, + pcie->pcie_data->cap_offset + PCI_EXP_LNKSTA); + + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); +} + /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -432,6 +486,101 @@ static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, return PCIBIOS_SUCCESSFUL; } +static int aglx_rp_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 *value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + *value = readb(addr); + break; + case 2: + *value = readw(addr); + break; + default: + *value = readl(addr); + break; + } + + /* interrupt pin not programmed in hardware, set to INTA*/ + if (where == PCI_INTERRUPT_PIN && size == 1) + *value = 0x01; + else if (where == PCI_INTERRUPT_LINE) + *value |= 0x0100; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_rp_write_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, + int where, int size, u32 value) +{ + void __iomem *addr = AGLX_RP_CFG_ADDR(pcie, where); + + switch (size) { + case 1: + writeb(value, addr); + break; + case 2: + writew(value, addr); + break; + default: + writel(value, addr); + break; + } + + /* + * Monitor changes to PCI_PRIMARY_BUS register on root port + * and update local copy of root bus number accordingly. + */ + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) + pcie->root_bus_nr = value & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_write_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + cs_writeb(pcie, value, where); + break; + case 2: + cs_writew(pcie, value, where); + break; + default: + cs_writel(pcie, value, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int aglx_nonrp_read_cfg(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, u32 *value) +{ + cs_writel(pcie, ((busno<<8) | devfn), AGLX_BDF_REG); + if (busno > AGLX_RP_SECONDARY(pcie)) + where |= (1<<12); /* type 1 */ + + switch (size) { + case 1: + *value = cs_readb(pcie, where); + break; + case 2: + *value = cs_readw(pcie, where); + break; + default: + *value = cs_readl(pcie, where); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int arr_read_cfg(struct altera_pcie *pcie, u8 busno, u32 devfn, int where, int size, u32 *value) { @@ -688,6 +837,30 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static void aglx_isr(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct altera_pcie *pcie; + struct device *dev; + u32 status; + int ret; + + chained_irq_enter(chip, desc); + pcie = irq_desc_get_handler_data(desc); + dev = &pcie->pdev->dev; + + status = readl((pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + if (status & AGLX_CFG_AER) { + ret = generic_handle_domain_irq(pcie->irq_domain, 0); + if (ret) + dev_err_ratelimited(dev, "unexpected IRQ\n"); + } + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_STATUS)); + chained_irq_exit(chip, desc); +} + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -723,13 +896,25 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return PTR_ERR(pcie->cra_base); } - if (pcie->pcie_data->version == ALTERA_PCIE_V2) { + if ((pcie->pcie_data->version == ALTERA_PCIE_V2) || + (pcie->pcie_data->version == ALTERA_PCIE_V3)) { pcie->hip_base = devm_platform_ioremap_resource_byname(pdev, "Hip"); if (IS_ERR(pcie->hip_base)) return PTR_ERR(pcie->hip_base); } + if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + pcie->cs_base = + devm_platform_ioremap_resource_byname(pdev, "Cs"); + if (IS_ERR(pcie->cs_base)) + return PTR_ERR(pcie->cs_base); + of_property_read_u32(pcie->pdev->dev.of_node, "port_conf_stat", + &pcie->port_conf_off); + dev_dbg(&pcie->pdev->dev, "port_conf_stat_off =%#x\n", + pcie->port_conf_off); + } + /* setup IRQ */ pcie->irq = platform_get_irq(pdev, 0); if (pcie->irq < 0) @@ -767,6 +952,15 @@ static const struct altera_pcie_ops altera_pcie_ops_2_0 = { .rp_isr = altera_pcie_isr, }; +static const struct altera_pcie_ops altera_pcie_ops_3_0 = { + .rp_read_cfg = aglx_rp_read_cfg, + .rp_write_cfg = aglx_rp_write_cfg, + .get_link_status = aglx_altera_pcie_link_up, + .nonrp_read_cfg = aglx_nonrp_read_cfg, + .nonrp_write_cfg = aglx_nonrp_write_cfg, + .rp_isr = aglx_isr, +}; + static const struct altera_pcie_data altera_pcie_1_0_data = { .ops = &altera_pcie_ops_1_0, .cap_offset = 0x80, @@ -787,11 +981,19 @@ static const struct altera_pcie_data altera_pcie_2_0_data = { .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, }; +static const struct altera_pcie_data altera_pcie_3_0_data = { + .ops = &altera_pcie_ops_3_0, + .version = ALTERA_PCIE_V3, + .cap_offset = 0x70, +}; + static const struct of_device_id altera_pcie_of_match[] = { {.compatible = "altr,pcie-root-port-1.0", .data = &altera_pcie_1_0_data }, {.compatible = "altr,pcie-root-port-2.0", .data = &altera_pcie_2_0_data }, + {.compatible = "altr,pcie-root-port-3.0", + .data = &altera_pcie_3_0_data }, {}, }; @@ -836,6 +1038,9 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); altera_pcie_host_init(pcie); + } else if (pcie->pcie_data->version == ALTERA_PCIE_V3) { + writel(AGLX_CFG_AER, (pcie->hip_base + pcie->port_conf_off + + AGLX_ROOT_PORT_IRQ_ENABLE)); } bridge->sysdata = pcie; -- 2.34.1 ^ permalink raw reply related [flat|nested] 56+ messages in thread
end of thread, other threads:[~2023-10-28 13:32 UTC | newest] Thread overview: 56+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-06-16 6:33 [PATCH 0/1] pci: agilex_rp: add pci root port support for agilex platform sharath.kumar.d.m 2023-06-16 6:33 ` [PATCH 1/1] pci: agilex_pci: add pcie rootport support for agilex sharath.kumar.d.m 2023-06-16 15:21 ` Bjorn Helgaas 2023-09-06 11:09 ` [PATCH v2 0/2] PCI: Altera: add support to Agilex family sharath.kumar.d.m 2023-09-06 11:09 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m 2023-09-06 17:08 ` Bjorn Helgaas 2023-09-08 9:09 ` D M, Sharath Kumar 2023-09-08 12:44 ` Bjorn Helgaas 2023-09-08 13:40 ` D M, Sharath Kumar 2023-09-08 19:52 ` Bjorn Helgaas 2023-09-11 10:33 ` [PATCH 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 12:24 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:35 ` [PATCH v2 1/2] PCI: altera: refactor driver for supporting new platform D M, Sharath Kumar 2023-09-11 20:08 ` Bjorn Helgaas 2023-09-13 12:59 ` Bjorn Helgaas 2023-09-17 17:05 ` [PATCH v4 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-17 17:05 ` [PATCH v4 1/2] PCI: altera: refactor driver for supporting new platform sharath.kumar.d.m 2023-09-17 17:05 ` [PATCH v4 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-10-25 22:05 ` Bjorn Helgaas 2023-10-28 13:26 ` [PATCH v5 2/2] PCI: altera: add support for agilex7 " sharath.kumar.d.m 2023-10-25 21:51 ` [PATCH v4 0/2] PCI: altera: add support to agilex family Bjorn Helgaas 2023-10-28 13:33 ` [PATCH v5 " sharath.kumar.d.m 2023-09-11 13:53 ` [PATCH v3 " sharath.kumar.d.m 2023-09-11 13:53 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:53 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-15 10:51 ` [PATCH v3 0/2] PCI: altera: add support to agilex family Dinh Nguyen 2023-09-06 11:09 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA sharath.kumar.d.m 2023-09-06 17:12 ` Bjorn Helgaas 2023-09-08 9:15 ` D M, Sharath Kumar 2023-09-08 12:47 ` Bjorn Helgaas 2023-09-08 14:35 ` D M, Sharath Kumar 2023-09-08 19:48 ` Bjorn Helgaas 2023-09-11 10:38 ` [PATCH 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:08 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 14:08 ` [PATCH v2 2/2] PCI: altera: add suport for Agilex Family FPGA D M, Sharath Kumar 2023-09-11 13:16 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:16 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:16 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:22 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:22 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:22 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:25 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 10:15 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 12:16 ` sharath.kumar.d.m 2023-09-11 13:31 ` sharath.kumar.d.m 2023-09-11 13:31 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:31 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m 2023-09-11 13:45 ` [PATCH v3 0/2] PCI: altera: add support to agilex family sharath.kumar.d.m 2023-09-11 13:45 ` [PATCH v3 1/2] PCI: altera: refactor driver for supporting new platforms sharath.kumar.d.m 2023-09-11 13:45 ` [PATCH v3 2/2] PCI: altera: add support for agilex family fpga sharath.kumar.d.m
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).