[U-Boot] [PATCH 0/3] dm: pcie_fsl: Fix some issues

The current driver is not working on some PowerPC T-series, P-series and MPC85xx platforms due to the difference in PCIe IP revisions and the various integration on different platforms. This patch set fixes these issues.
Hou Zhiqiang (3): dm: pcie_fsl: Fix workaround of P4080 erratum A003 dm: pcie_fsl: Fix the Class Code fixup function dm: pcie_fsl: Fix the calculation of controller index
drivers/pci/pcie_fsl.c | 33 ++++++++++++++++++++++++++------- drivers/pci/pcie_fsl.h | 16 ++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-)

In the workaround of P4080 erratum A003, it uses the macro CONFIG_SYS_FSL_CORENET_SERDES_ADDR to get the SerDes block register address, the CONFIG_SYS_FSL_CORENET_SERDES_ADDR is defined as following:
#define CONFIG_SYS_FSL_CORENET_SERDES_ADDR \ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
This is valid on P4080, but on non-corenet platforms, such as MPC8548, there is not definition of CONFIG_SYS_FSL_CORENET_SERDES_OFFSET, then on these platforms the following build error will come up:
drivers/pci/pcie_fsl.c: In function 'fsl_pcie_init_port': ./arch/powerpc/include/asm/immap_85xx.h:3000:21: error: 'CONFIG_SYS_FSL_CORENET_SERDES_OFFSET' undeclared (first use in this function); did you mean 'CONFIG_SYS_FSL_CORENET_SERDES_ADDR'? (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES_OFFSET) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- drivers/pci/pcie_fsl.c | 2 +- drivers/pci/pcie_fsl.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c index bfb207e..999e9c9 100644 --- a/drivers/pci/pcie_fsl.c +++ b/drivers/pci/pcie_fsl.c @@ -445,7 +445,7 @@ static int fsl_pcie_init_port(struct fsl_pcie *pcie) !fsl_pcie_link_up(pcie)) { serdes_corenet_t *srds_regs;
- srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; + srds_regs = (void *)P4080_SERDES_ADDR; val_32 = in_be32(&srds_regs->srdspccr0);
if ((val_32 >> 28) == 3) { diff --git a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h index ce2b1af..e09099b 100644 --- a/drivers/pci/pcie_fsl.h +++ b/drivers/pci/pcie_fsl.h @@ -41,6 +41,12 @@ #define LTSSM_L0_REV3 0x11 #define LTSSM_L0 0x16
+#ifdef ARCH_P4080 +#define P4080_SERDES_ADDR CONFIG_SYS_FSL_CORENET_SERDES_ADDR +#else +#define P4080_SERDES_ADDR 0 +#endif + struct fsl_pcie { int idx; struct udevice *bus;

On Tue, Jul 23, 2019 at 8:53 PM Hou Zhiqiang Zhiqiang.Hou@nxp.com wrote:
In the workaround of P4080 erratum A003, it uses the macro CONFIG_SYS_FSL_CORENET_SERDES_ADDR to get the SerDes block register address, the CONFIG_SYS_FSL_CORENET_SERDES_ADDR is defined as following:
#define CONFIG_SYS_FSL_CORENET_SERDES_ADDR \ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
This is valid on P4080, but on non-corenet platforms, such as MPC8548, there is not definition of CONFIG_SYS_FSL_CORENET_SERDES_OFFSET, then on these platforms the following build error will come up:
drivers/pci/pcie_fsl.c: In function 'fsl_pcie_init_port': ./arch/powerpc/include/asm/immap_85xx.h:3000:21: error: 'CONFIG_SYS_FSL_CORENET_SERDES_OFFSET' undeclared (first use in this function); did you mean 'CONFIG_SYS_FSL_CORENET_SERDES_ADDR'? (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES_OFFSET) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/pci/pcie_fsl.c | 2 +- drivers/pci/pcie_fsl.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c index bfb207e..999e9c9 100644 --- a/drivers/pci/pcie_fsl.c +++ b/drivers/pci/pcie_fsl.c @@ -445,7 +445,7 @@ static int fsl_pcie_init_port(struct fsl_pcie *pcie) !fsl_pcie_link_up(pcie)) { serdes_corenet_t *srds_regs;
srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
srds_regs = (void *)P4080_SERDES_ADDR; val_32 = in_be32(&srds_regs->srdspccr0); if ((val_32 >> 28) == 3) {
diff --git a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h index ce2b1af..e09099b 100644 --- a/drivers/pci/pcie_fsl.h +++ b/drivers/pci/pcie_fsl.h @@ -41,6 +41,12 @@ #define LTSSM_L0_REV3 0x11 #define LTSSM_L0 0x16
+#ifdef ARCH_P4080 +#define P4080_SERDES_ADDR CONFIG_SYS_FSL_CORENET_SERDES_ADDR +#else +#define P4080_SERDES_ADDR 0
So for non-P4080 platform, we are accessing address at zero?
Regards, Bin

Hi Bin,
Sorry for my delay respond, and thanks for your comments!
-----Original Message----- From: Bin Meng [mailto:bmeng.cn@gmail.com] Sent: 2019年7月23日 21:04 To: Z.q. Hou zhiqiang.hou@nxp.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com Subject: Re: [U-Boot] [PATCH 1/3] dm: pcie_fsl: Fix workaround of P4080 erratum A003
On Tue, Jul 23, 2019 at 8:53 PM Hou Zhiqiang Zhiqiang.Hou@nxp.com wrote:
In the workaround of P4080 erratum A003, it uses the macro CONFIG_SYS_FSL_CORENET_SERDES_ADDR to get the SerDes block register address, the CONFIG_SYS_FSL_CORENET_SERDES_ADDR is defined as following:
#define CONFIG_SYS_FSL_CORENET_SERDES_ADDR \ (CONFIG_SYS_IMMR +
CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
This is valid on P4080, but on non-corenet platforms, such as MPC8548, there is not definition of CONFIG_SYS_FSL_CORENET_SERDES_OFFSET, then on these platforms the following build error will come up:
drivers/pci/pcie_fsl.c: In function 'fsl_pcie_init_port': ./arch/powerpc/include/asm/immap_85xx.h:3000:21: error: 'CONFIG_SYS_FSL_CORENET_SERDES_OFFSET' undeclared (first use in this function); did you mean 'CONFIG_SYS_FSL_CORENET_SERDES_ADDR'? (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/pci/pcie_fsl.c | 2 +- drivers/pci/pcie_fsl.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c index bfb207e..999e9c9 100644 --- a/drivers/pci/pcie_fsl.c +++ b/drivers/pci/pcie_fsl.c @@ -445,7 +445,7 @@ static int fsl_pcie_init_port(struct fsl_pcie *pcie) !fsl_pcie_link_up(pcie)) { serdes_corenet_t *srds_regs;
srds_regs = (void
*)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
srds_regs = (void *)P4080_SERDES_ADDR; val_32 = in_be32(&srds_regs->srdspccr0); if ((val_32 >> 28) == 3) { diff --git
a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h index ce2b1af..e09099b 100644 --- a/drivers/pci/pcie_fsl.h +++ b/drivers/pci/pcie_fsl.h @@ -41,6 +41,12 @@ #define LTSSM_L0_REV3 0x11 #define LTSSM_L0 0x16
+#ifdef ARCH_P4080 +#define P4080_SERDES_ADDR
CONFIG_SYS_FSL_CORENET_SERDES_ADDR
+#else +#define P4080_SERDES_ADDR 0
So for non-P4080 platform, we are accessing address at zero?
This macro is only used in the workaround of P4080 Erratum A003, so for non-P4080, it won't run into this workaround.
Thanks, Zhiqiang
Regards, Bin

On Fri, Aug 23, 2019 at 10:43 AM Z.q. Hou zhiqiang.hou@nxp.com wrote:
Hi Bin,
Sorry for my delay respond, and thanks for your comments!
-----Original Message----- From: Bin Meng [mailto:bmeng.cn@gmail.com] Sent: 2019年7月23日 21:04 To: Z.q. Hou zhiqiang.hou@nxp.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com Subject: Re: [U-Boot] [PATCH 1/3] dm: pcie_fsl: Fix workaround of P4080 erratum A003
On Tue, Jul 23, 2019 at 8:53 PM Hou Zhiqiang Zhiqiang.Hou@nxp.com wrote:
In the workaround of P4080 erratum A003, it uses the macro CONFIG_SYS_FSL_CORENET_SERDES_ADDR to get the SerDes block register address, the CONFIG_SYS_FSL_CORENET_SERDES_ADDR is defined as following:
#define CONFIG_SYS_FSL_CORENET_SERDES_ADDR \ (CONFIG_SYS_IMMR +
CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
This is valid on P4080, but on non-corenet platforms, such as MPC8548, there is not definition of CONFIG_SYS_FSL_CORENET_SERDES_OFFSET, then on these platforms the following build error will come up:
drivers/pci/pcie_fsl.c: In function 'fsl_pcie_init_port': ./arch/powerpc/include/asm/immap_85xx.h:3000:21: error: 'CONFIG_SYS_FSL_CORENET_SERDES_OFFSET' undeclared (first use in this function); did you mean 'CONFIG_SYS_FSL_CORENET_SERDES_ADDR'? (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/pci/pcie_fsl.c | 2 +- drivers/pci/pcie_fsl.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c index bfb207e..999e9c9 100644 --- a/drivers/pci/pcie_fsl.c +++ b/drivers/pci/pcie_fsl.c @@ -445,7 +445,7 @@ static int fsl_pcie_init_port(struct fsl_pcie *pcie) !fsl_pcie_link_up(pcie)) { serdes_corenet_t *srds_regs;
srds_regs = (void
*)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
srds_regs = (void *)P4080_SERDES_ADDR; val_32 = in_be32(&srds_regs->srdspccr0); if ((val_32 >> 28) == 3) { diff --git
a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h index ce2b1af..e09099b 100644 --- a/drivers/pci/pcie_fsl.h +++ b/drivers/pci/pcie_fsl.h @@ -41,6 +41,12 @@ #define LTSSM_L0_REV3 0x11 #define LTSSM_L0 0x16
+#ifdef ARCH_P4080 +#define P4080_SERDES_ADDR
CONFIG_SYS_FSL_CORENET_SERDES_ADDR
+#else +#define P4080_SERDES_ADDR 0
So for non-P4080 platform, we are accessing address at zero?
This macro is only used in the workaround of P4080 Erratum A003, so for non-P4080, it won't run into this workaround.
Still don't get it. Then why not use #ifdef P4080_Erratum_A003 #endif ?
Regards, Bin

Hi Bin,
Thanks a lot for your comments!
-----Original Message----- From: Bin Meng [mailto:bmeng.cn@gmail.com] Sent: 2019年8月23日 11:15 To: Z.q. Hou zhiqiang.hou@nxp.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com Subject: Re: [U-Boot] [PATCH 1/3] dm: pcie_fsl: Fix workaround of P4080 erratum A003
On Fri, Aug 23, 2019 at 10:43 AM Z.q. Hou zhiqiang.hou@nxp.com wrote:
Hi Bin,
Sorry for my delay respond, and thanks for your comments!
-----Original Message----- From: Bin Meng [mailto:bmeng.cn@gmail.com] Sent: 2019年7月23日 21:04 To: Z.q. Hou zhiqiang.hou@nxp.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com Subject: Re: [U-Boot] [PATCH 1/3] dm: pcie_fsl: Fix workaround of P4080 erratum A003
On Tue, Jul 23, 2019 at 8:53 PM Hou Zhiqiang Zhiqiang.Hou@nxp.com wrote:
In the workaround of P4080 erratum A003, it uses the macro CONFIG_SYS_FSL_CORENET_SERDES_ADDR to get the SerDes block register address, the CONFIG_SYS_FSL_CORENET_SERDES_ADDR is defined as following:
#define CONFIG_SYS_FSL_CORENET_SERDES_ADDR \ (CONFIG_SYS_IMMR +
CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
This is valid on P4080, but on non-corenet platforms, such as MPC8548, there is not definition of CONFIG_SYS_FSL_CORENET_SERDES_OFFSET, then on these platforms
the following build error will come up:
drivers/pci/pcie_fsl.c: In function 'fsl_pcie_init_port': ./arch/powerpc/include/asm/immap_85xx.h:3000:21: error: 'CONFIG_SYS_FSL_CORENET_SERDES_OFFSET' undeclared (first use in this function); did you mean
'CONFIG_SYS_FSL_CORENET_SERDES_ADDR'?
(CONFIG_SYS_IMMR +
CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/pci/pcie_fsl.c | 2 +- drivers/pci/pcie_fsl.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c index bfb207e..999e9c9 100644 --- a/drivers/pci/pcie_fsl.c +++ b/drivers/pci/pcie_fsl.c @@ -445,7 +445,7 @@ static int fsl_pcie_init_port(struct fsl_pcie *pcie) !fsl_pcie_link_up(pcie)) { serdes_corenet_t *srds_regs;
srds_regs = (void
*)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
srds_regs = (void *)P4080_SERDES_ADDR; val_32 = in_be32(&srds_regs->srdspccr0); if ((val_32 >> 28) == 3) { diff --git
a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h index ce2b1af..e09099b 100644 --- a/drivers/pci/pcie_fsl.h +++ b/drivers/pci/pcie_fsl.h @@ -41,6 +41,12 @@ #define LTSSM_L0_REV3 0x11 #define LTSSM_L0 0x16
+#ifdef ARCH_P4080 +#define P4080_SERDES_ADDR
CONFIG_SYS_FSL_CORENET_SERDES_ADDR
+#else +#define P4080_SERDES_ADDR 0
So for non-P4080 platform, we are accessing address at zero?
This macro is only used in the workaround of P4080 Erratum A003, so for
non-P4080, it won't run into this workaround.
Still don't get it. Then why not use #ifdef P4080_Erratum_A003 #endif ?
Make sense, will change in v2.
Thanks, Zhiqiang
Regards, Bin

The Class Code fixup method was changed from PCIe block revision 3.0, the current fixup is only valid for the revision 3.0 and the later ones.
This patch is to add the Class Code fixup for the block revision < 3.0.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- drivers/pci/pcie_fsl.c | 17 +++++++++++++---- drivers/pci/pcie_fsl.h | 3 +++ 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c index 999e9c9..7a7da1f 100644 --- a/drivers/pci/pcie_fsl.c +++ b/drivers/pci/pcie_fsl.c @@ -503,12 +503,21 @@ static int fsl_pcie_fixup_classcode(struct fsl_pcie *pcie) ccsr_fsl_pci_t *regs = pcie->regs; u32 val;
- setbits_be32(®s->dbi_ro_wr_en, 0x01); - fsl_pcie_hose_read_config_dword(pcie, PCI_CLASS_REVISION, &val); + if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) { + setbits_be32(®s->dbi_ro_wr_en, 0x01); + fsl_pcie_hose_read_config_dword(pcie, PCI_CLASS_REVISION, &val); + val &= 0xff; + val |= PCI_CLASS_BRIDGE_PCI << 16; + fsl_pcie_hose_write_config_dword(pcie, PCI_CLASS_REVISION, val); + clrbits_be32(®s->dbi_ro_wr_en, 0x01); + + return 0; + } + + fsl_pcie_hose_read_config_dword(pcie, CSR_CLASSCODE, &val); val &= 0xff; val |= PCI_CLASS_BRIDGE_PCI << 16; - fsl_pcie_hose_write_config_dword(pcie, PCI_CLASS_REVISION, val); - clrbits_be32(®s->dbi_ro_wr_en, 0x01); + fsl_pcie_hose_write_config_dword(pcie, CSR_CLASSCODE, val);
return 0; } diff --git a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h index e09099b..a872921 100644 --- a/drivers/pci/pcie_fsl.h +++ b/drivers/pci/pcie_fsl.h @@ -10,6 +10,9 @@ #ifndef _PCIE_FSL_H_ #define _PCIE_FSL_H_
+/* GPEX CSR */ +#define CSR_CLASSCODE 0x474 + #ifdef CONFIG_SYS_FSL_PCI_VER_3_X #define FSL_PCIE_CAP_ID 0x70 #else

The PCIe controller register address in CCSR is different on various platforms, the current code erroneously use the hardcoded address (0xffe240000) and stride (0x10000) to calculate the controller's index.
Fix it by adding the related info to the driver data structure.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- drivers/pci/pcie_fsl.c | 14 ++++++++++++-- drivers/pci/pcie_fsl.h | 7 +++++++ 2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c index 7a7da1f..e13e5a6 100644 --- a/drivers/pci/pcie_fsl.c +++ b/drivers/pci/pcie_fsl.c @@ -580,6 +580,7 @@ static int fsl_pcie_probe(struct udevice *dev) static int fsl_pcie_ofdata_to_platdata(struct udevice *dev) { struct fsl_pcie *pcie = dev_get_priv(dev); + struct fsl_pcie_data *info; int ret;
pcie->regs = dev_remap_addr(dev); @@ -594,7 +595,10 @@ static int fsl_pcie_ofdata_to_platdata(struct udevice *dev) return ret; }
- pcie->idx = (dev_read_addr(dev) - 0xffe240000) / 0x10000; + info = (struct fsl_pcie_data *)dev_get_driver_data(dev); + pcie->info = info; + pcie->idx = abs((u32)(dev_read_addr(dev) & info->block_offset_mask) - + info->block_offset) / info->stride;
return 0; } @@ -604,8 +608,14 @@ static const struct dm_pci_ops fsl_pcie_ops = { .write_config = fsl_pcie_write_config, };
+static struct fsl_pcie_data t2080_data = { + .block_offset = 0x240000, + .block_offset_mask = 0x3fffff, + .stride = 0x10000, +}; + static const struct udevice_id fsl_pcie_ids[] = { - { .compatible = "fsl,pcie-t2080" }, + { .compatible = "fsl,pcie-t2080", .data = (ulong)&t2080_data }, { } };
diff --git a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h index a872921..8335c62 100644 --- a/drivers/pci/pcie_fsl.h +++ b/drivers/pci/pcie_fsl.h @@ -50,6 +50,12 @@ #define P4080_SERDES_ADDR 0 #endif
+struct fsl_pcie_data { + u32 block_offset; /* Offset from CCSR of 1st controller */ + u32 block_offset_mask; /* Mask out the CCSR base */ + u32 stride; /* Offset stride between controllers */ +}; + struct fsl_pcie { int idx; struct udevice *bus; @@ -59,6 +65,7 @@ struct fsl_pcie { bool mode; /* RC&EP mode flag */ bool enabled; /* Enable status */ struct list_head list; + struct fsl_pcie_data *info; };
extern struct list_head fsl_pcie_list;
participants (3)
-
Bin Meng
-
Hou Zhiqiang
-
Z.q. Hou