Re: [PATCH] fpga: altera-cvp: Add Agilex5 CVP credit register support
Xu Yilun <[email protected]> Sat, 27 Jun 2026 00:37:00 +0800
| Newsgroups | org.kernel.vger.linux-fpga,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <aj6qrFag+NOvGrKr@yilunxu-OptiPlex-7050> |
On Thu, Jun 18, 2026 at 08:43:27PM -0700, [email protected] wrote: > From: Nazim Amirul <[email protected]> > > Extend the CvP driver to support Agilex5, which uses a different > register layout than previous SoC FPGA variants for CVP bitstream > transfer. > > Agilex5 uses a different VSEC layout (VSEC length 0x60) and a > dedicated CVP credit register at offset 0x5C with 12-bit width, > compared to offset 0x49 with 8-bit width on other platforms. > > Detect the device family at probe time by reading the VSEC specific > header and checking the VSEC length field. Introduce > device_family_type to distinguish V1, V2, and V2 Agilex5 variants. > Use altera_read_config_dword() with a 0xFFF mask for Agilex5 credits > and altera_read_config_byte() for all other devices. > Fix the credit > comparison by removing the incorrect u8 cast on sent_packets. Is it a bug fix for existing cases? If yes, split it out to a separate patch. Otherwise, don't say 'fix'. > > Signed-off-by: Nazim Amirul <[email protected]> > --- > drivers/fpga/altera-cvp.c | 48 +++++++++++++++++++++++++++++++++++---- > 1 file changed, 43 insertions(+), 5 deletions(-) > > diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c > index 44badfd11e1b..58128de2a8c5 100644 > --- a/drivers/fpga/altera-cvp.c > +++ b/drivers/fpga/altera-cvp.c > @@ -10,6 +10,7 @@ > * Firmware must be in binary "rbf" format. > */ > > +#include <linux/bitfield.h> > #include <linux/delay.h> > #include <linux/device.h> > #include <linux/fpga/fpga-mgr.h> > @@ -22,6 +23,9 @@ > #define TIMEOUT_US 2000 /* CVP STATUS timeout for USERMODE polling */ > > /* Vendor Specific Extended Capability Registers */ > +#define VSE_PCIE_SPECIFIC_HEADER 0x4 /* VSEC ID, Revision, length */ > +#define VSEC_LENGTH GENMASK(31, 20) Are they PCIe standard registers? > +#define AGILEX5_VSEC_LENGTH 0x60 /* Agilex5 only */ > #define VSE_CVP_STATUS 0x1c /* 32bit */ > #define VSE_CVP_STATUS_CFG_RDY BIT(18) /* CVP_CONFIG_READY */ > #define VSE_CVP_STATUS_CFG_ERR BIT(19) /* CVP_CONFIG_ERROR */ > @@ -48,6 +52,7 @@ > #define V1_VSEC_OFFSET 0x200 /* Vendor Specific Offset V1 */ > /* V2 Defines */ > #define VSE_CVP_TX_CREDITS 0x49 /* 8bit */ > +#define VSE_CVP_AG5_TX_CREDITS 0x5C /* 12bit credits for Agilex5 */ > > #define V2_CREDIT_TIMEOUT_US 40000 > #define V2_CHECK_CREDIT_US 10 > @@ -58,6 +63,9 @@ > > #define DRV_NAME "altera-cvp" > #define ALTERA_CVP_MGR_NAME "Altera CvP FPGA Manager" > +#define SOCFPGA_CVP_V1_OTHERS 0x1 > +#define SOCFPGA_CVP_V2_OTHERS 0x2 I didn't see they are used anywhere. > +#define SOCFPGA_CVP_V2_AGILEX5 0x3 > > /* Write block sizes */ > #define ALTERA_CVP_V1_SIZE 4 > @@ -78,6 +86,7 @@ struct altera_cvp_conf { > u32 sent_packets; > u32 vsec_offset; > const struct cvp_priv *priv; > + u32 device_family_type; > }; > > struct cvp_priv { > @@ -228,18 +237,32 @@ static int altera_cvp_v2_wait_for_credit(struct fpga_manager *mgr, > u32 timeout = V2_CREDIT_TIMEOUT_US / V2_CHECK_CREDIT_US; > struct altera_cvp_conf *conf = mgr->priv; > int ret; > - u8 val; > + u32 val; > + u32 credit_mask = GENMASK(7, 0); > + u32 vse_cvp_tx_credits_offset = VSE_CVP_TX_CREDITS; I'm not strict on reverse xmas tree, but don't make a complete mess. > + > + if (conf->device_family_type == SOCFPGA_CVP_V2_AGILEX5) { > + vse_cvp_tx_credits_offset = VSE_CVP_AG5_TX_CREDITS; > + credit_mask = GENMASK(11, 0); > + } > > do { > - ret = altera_read_config_byte(conf, VSE_CVP_TX_CREDITS, &val); > + /* READ DWORD is required for Agilex5 but READ BYTE is required for non-Agilex5 */ > + if (conf->device_family_type == SOCFPGA_CVP_V2_AGILEX5) > + ret = altera_read_config_dword(conf, vse_cvp_tx_credits_offset, &val); > + else > + ret = altera_read_config_byte(conf, vse_cvp_tx_credits_offset, (u8 *)&val); > + > if (ret) { > dev_err(&conf->pci_dev->dev, > "Error reading CVP Credit Register\n"); > return ret; > } > > + val = val & credit_mask; Don't you have struct cvp_priv to describe HW differences? Why not use it? Why Bifurcating code like this? > + > /* Return if there is space in FIFO */ > - if (val - (u8)conf->sent_packets) > + if (val - conf->sent_packets) > return 0; > > ret = altera_cvp_chk_error(mgr, blocks * ALTERA_CVP_V2_SIZE); > @@ -507,6 +530,8 @@ static int altera_cvp_write_complete(struct fpga_manager *mgr, > conf->priv->user_time_us); > if (ret) > dev_err(&mgr->dev, "PLD_CLK_IN_USE|USERMODE timeout\n"); > + else > + dev_notice(&mgr->dev, "CVP write completed successfully.\n"); Why adding this print, anything to do with "support Agilex5"? > > return ret; > } > @@ -627,10 +652,23 @@ static int altera_cvp_probe(struct pci_dev *pdev, > conf->pci_dev = pdev; > conf->write_data = altera_cvp_write_data_iomem; > > - if (conf->vsec_offset == V1_VSEC_OFFSET) > + /* To differentiate the target SOCFPGA */ > + if (conf->vsec_offset == V1_VSEC_OFFSET) { > conf->priv = &cvp_priv_v1; > - else > + conf->device_family_type = SOCFPGA_CVP_V1_OTHERS; Why add another board type indicator, conf->priv won't work? > + dev_notice(&pdev->dev, "V1 target SOCFPGA detected.\n"); No news is good news, a good driver keeps quiet. > + } else { > + /* Agilex7, Stratix10, Agilex5*/ > conf->priv = &cvp_priv_v2; > + pci_read_config_dword(pdev, offset + VSE_PCIE_SPECIFIC_HEADER, ®val); > + if (FIELD_GET(VSEC_LENGTH, regval) == AGILEX5_VSEC_LENGTH) { > + conf->device_family_type = SOCFPGA_CVP_V2_AGILEX5; > + dev_notice(&pdev->dev, "V2 target SOCFPGA Agilex5 detected.\n"); > + } else { > + conf->device_family_type = SOCFPGA_CVP_V2_OTHERS; > + dev_notice(&pdev->dev, "V2 target SOCFPGA detected.\n"); > + } > + } BTW: I really suggest you don't send multiple threads at a time. Getting the first patch right, then I'll have confidence to move to the next. > > conf->map = pci_iomap(pdev, CVP_BAR, 0); > if (!conf->map) { > -- > 2.43.7 > >