[U-Boot] [PATCH] Powerpc: Make pcie link state judge more specific

Mingkai Hu mingkai.hu at nxp.com
Tue Oct 10 10:30:07 UTC 2017



> -----Original Message-----
> From: Bao Xiaowei [mailto:xiaowei.bao at nxp.com]
> Sent: Monday, September 25, 2017 11:27 AM
> To: M.h. Lian <minghuan.lian at nxp.com>; Z.q. Hou <zhiqiang.hou at nxp.com>;
> Mingkai Hu <mingkai.hu at nxp.com>; York Sun <york.sun at nxp.com>;
> hamish.martin at alliedtelesis.co.nz; wd at denx.de;
> tony.obrien at alliedtelesis.co.nz; u-boot at lists.denx.de
> Cc: Xiaowei Bao <xiaowei.bao at nxp.com>
> Subject: [PATCH] Powerpc: Make pcie link state judge more specific
> 
> For some special reset times for longer pcie devices, in this case, the pcie
> device may on polling compliance state, the RC considers the pcie device is
> link up, but the pcie device is not link up, only the L0 state is link up state. So
> add the link up status judgement mechanisms.
> 
> Signed-off-by: Bao Xiaowei <xiaowei.bao at nxp.com>
> ---
> v2:
>  - Detailed function module
>  - Adjust the code structure
> 

I suggest to split this patch to two patches, one is for format change, another one is for LTSSM change.

>  arch/powerpc/include/asm/fsl_pci.h |   3 +
>  drivers/pci/fsl_pci_init.c         | 151 ++++++++++++++++++++-----------------
>  2 files changed, 86 insertions(+), 68 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/fsl_pci.h
> b/arch/powerpc/include/asm/fsl_pci.h
> index cad341e..9dfbf19 100644
> --- a/arch/powerpc/include/asm/fsl_pci.h
> +++ b/arch/powerpc/include/asm/fsl_pci.h
> @@ -24,6 +24,9 @@
> 
>  #define PCI_LTSSM	0x404   /* PCIe Link Training, Status State Machine */
>  #define  PCI_LTSSM_L0	0x16    /* L0 state */

It's better to submit a patch to fix the leading space.

> +#define PCIE_GEN3_LTSSM_L0     0x11    /* L0 state */

Follow the same name rule as PCI_LTSSM_L0? Like PCI_LTSSM_L0_PEX_REV3?

> +#define LTSSM_PCIE_DETECT_QUIET                0x00 /* Detect state */
> +#define LTSSM_PCIE_DETECT_ACTIVE       0x01 /* Detect state */
> 
>  int fsl_setup_hose(struct pci_controller *hose, unsigned long addr);  int
> fsl_is_pci_agent(struct pci_controller *hose); diff --git
> a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index af20cf0..5d697bc
> 100644
> --- a/drivers/pci/fsl_pci_init.c
> +++ b/drivers/pci/fsl_pci_init.c
> @@ -39,6 +39,8 @@ DECLARE_GLOBAL_DATA_PTR;  #if
> defined(CONFIG_SYS_PCI_64BIT)
> && !defined(CONFIG_SYS_PCI64_MEMORY_BUS)
>  #define CONFIG_SYS_PCI64_MEMORY_BUS (64ull*1024*1024*1024)  #endif
> +#define PEX_CSR0_LTSSM_MASK	0xFC
> +#define PEX_CSR0_LTSSM_SHIFT	2
> 
>  /* Setup one inbound ATMU window.
>   *
> @@ -290,6 +292,81 @@ static void fsl_pcie_boot_master_release_slave(int
> port)  }  #endif
> 
> +static int is_pcie_gen3(struct fsl_pci_info *pci_info) {
> +	u32 cfg_addr = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_addr;
> +	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr;
> +	u32 block_rev;
> +
> +	block_rev = in_be32(&pci->block_rev1);
> +	if (block_rev >= PEX_IP_BLK_REV_3_0)
> +		return 1;
> +	else
> +		return 0;
> +}
> +

As discussed, it's not related to gen3. It's related to PEX block version. Please use
The PCIe controller version here.

> +static int get_ltssm_val(struct pci_controller *hose,
> +			 struct fsl_pci_info *pci_info)
> +{
> +	u16 ltssm = 0;
> +	pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0);
> +	u32 cfg_addr = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_addr;
> +	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr;
> +
> +	if (is_pcie_gen3(pci_info))
> +		ltssm = (in_be32(&pci->pex_csr0)
> +			& PEX_CSR0_LTSSM_MASK) >>
> PEX_CSR0_LTSSM_SHIFT;
> +	else
> +		pci_hose_read_config_word(hose, dev, PCI_LTSSM, &ltssm);
> +
> +	return ltssm;
> +}
> +
> +static int pci_link_up(struct pci_controller *hose,
> +			struct fsl_pci_info *pci_info)
> +{
> +	int enabled = 0;
> +	u16 ltssm;
> +	int i, pcie_ltssm_l0;
> +
> +	if (is_pcie_gen3(pci_info))
> +		pcie_ltssm_l0 = PCIE_GEN3_LTSSM_L0;
> +	else
> +		pcie_ltssm_l0 = PCI_LTSSM_L0;
> +
> +	ltssm = get_ltssm_val(hose, pci_info);
> +	if (ltssm == LTSSM_PCIE_DETECT_QUIET ||
> +		ltssm == LTSSM_PCIE_DETECT_ACTIVE)
> +		enabled = 0;
> +	else if (ltssm == PCIE_GEN3_LTSSM_L0)
> +		enabled = 1;
> +	else {
> +		for (i = 0; i < 100 && ltssm != pcie_ltssm_l0; i++) {
> +			ltssm = get_ltssm_val(hose, pci_info);
> +			udelay(1000);
> +		}
> +		enabled = (ltssm == pcie_ltssm_l0) ? 1 : 0;
> +	}
> +	return enabled;
> +}
> +
> +#if defined(CONFIG_FSL_PCIE_RESET) || \
> +	defined(CONFIG_SYS_P4080_ERRATUM_PCIE_A003)
> +static void do_pcie_reset(struct fsl_pci_info *pci_info) {
> +	u32 cfg_addr = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_addr;
> +	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr;
> +
> +	/* assert PCIe reset */
> +	setbits_be32(&pci->pdb_stat, 0x08000000);
> +	(void) in_be32(&pci->pdb_stat);
> +	udelay(1000);
> +	/* clear PCIe reset */
> +	clrbits_be32(&pci->pdb_stat, 0x08000000);
> +	asm("sync;isync");
> +}
> +#endif
> +
>  void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)  {
>  	u32 cfg_addr = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_addr;
> @@ -298,7 +375,6 @@ void fsl_pci_init(struct pci_controller *hose, struct
> fsl_pci_info *pci_info)
>  	u32 temp32;
>  	u32 block_rev;
>  	int enabled, r, inbound = 0;
> -	u16 ltssm;
>  	u8 temp8, pcie_cap;
>  	int pcie_cap_pos;
>  	int pci_dcr;
> @@ -438,63 +514,12 @@ void fsl_pci_init(struct pci_controller *hose, struct
> fsl_pci_info *pci_info)
>  	udelay(1);
>  #endif
>  	if (pcie_cap == PCI_CAP_ID_EXP) {
> -		if (block_rev >= PEX_IP_BLK_REV_3_0) {
> -#define PEX_CSR0_LTSSM_MASK	0xFC
> -#define PEX_CSR0_LTSSM_SHIFT	2
> -			ltssm = (in_be32(&pci->pex_csr0)
> -				& PEX_CSR0_LTSSM_MASK) >>
> PEX_CSR0_LTSSM_SHIFT;
> -			enabled = (ltssm == 0x11) ? 1 : 0;
>  #ifdef CONFIG_FSL_PCIE_RESET
> -			int i;
> -			/* assert PCIe reset */
> -			setbits_be32(&pci->pdb_stat, 0x08000000);
> -			(void) in_be32(&pci->pdb_stat);
> -			udelay(1000);
> -			/* clear PCIe reset */
> -			clrbits_be32(&pci->pdb_stat, 0x08000000);
> -			asm("sync;isync");
> -			for (i = 0; i < 100 && ltssm < PCI_LTSSM_L0; i++) {
> -				pci_hose_read_config_word(hose, dev,
> PCI_LTSSM,
> -							  &ltssm);
> -				udelay(1000);
> -			}
> +		do_pcie_reset(pci_info);
> +		pci_hose_write_config_dword(hose, dev,
> +						PCI_BASE_ADDRESS_0,
> pcicsrbar);
>  #endif
> -		} else {
> -		/* pci_hose_read_config_word(hose, dev, PCI_LTSSM,
> &ltssm); */
> -		/* enabled = ltssm >= PCI_LTSSM_L0; */
> -		pci_hose_read_config_word(hose, dev, PCI_LTSSM, &ltssm);
> -		enabled = ltssm >= PCI_LTSSM_L0;
> -
> -#ifdef CONFIG_FSL_PCIE_RESET
> -		if (ltssm == 1) {
> -			int i;
> -			debug("....PCIe link error. " "LTSSM=0x%02x.", ltssm);
> -			/* assert PCIe reset */
> -			setbits_be32(&pci->pdb_stat, 0x08000000);
> -			(void) in_be32(&pci->pdb_stat);
> -			udelay(100);
> -			debug("  Asserting PCIe reset @%p = %x\n",
> -			      &pci->pdb_stat, in_be32(&pci->pdb_stat));
> -			/* clear PCIe reset */
> -			clrbits_be32(&pci->pdb_stat, 0x08000000);
> -			asm("sync;isync");
> -			for (i=0; i<100 && ltssm < PCI_LTSSM_L0; i++) {
> -				pci_hose_read_config_word(hose, dev,
> PCI_LTSSM,
> -							&ltssm);
> -				udelay(1000);
> -				debug("....PCIe link error. "
> -				      "LTSSM=0x%02x.\n", ltssm);
> -			}
> -			enabled = ltssm >= PCI_LTSSM_L0;
> -
> -			/* we need to re-write the bar0 since a reset will
> -			 * clear it
> -			 */
> -			pci_hose_write_config_dword(hose, dev,
> -					PCI_BASE_ADDRESS_0, pcicsrbar);
> -		}
> -#endif
> -	}
> +		enabled = pci_link_up(hose, pci_info);
> 
>  #ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003
>  		if (enabled == 0) {
> @@ -502,19 +527,9 @@ void fsl_pci_init(struct pci_controller *hose, struct
> fsl_pci_info *pci_info)
>  			temp32 = in_be32(&srds_regs->srdspccr0);
> 
>  			if ((temp32 >> 28) == 3) {
> -				int i;
> -
>  				out_be32(&srds_regs->srdspccr0, 2 << 28);
> -				setbits_be32(&pci->pdb_stat, 0x08000000);
> -				in_be32(&pci->pdb_stat);
> -				udelay(100);
> -				clrbits_be32(&pci->pdb_stat, 0x08000000);
> -				asm("sync;isync");
> -				for (i=0; i < 100 && ltssm < PCI_LTSSM_L0; i++)
> {
> -					pci_hose_read_config_word(hose,
> dev, PCI_LTSSM, &ltssm);
> -					udelay(1000);
> -				}
> -				enabled = ltssm >= PCI_LTSSM_L0;
> +				do_pcie_reset(pci_info);
> +				enabled = pci_link_up(hose, pci_info);
>  			}
>  		}
>  #endif
> --
> 2.7.4



More information about the U-Boot mailing list