[PATCH u-boot-marvell 7/9] arm: mvebu: a38x: serdes: Don't configure PCIe cards in SerDes init code

Stefan Roese sr at denx.de
Fri Oct 8 08:29:34 CEST 2021


On 24.09.21 22:59, Marek Behún wrote:
> From: Pali Rohár <pali at kernel.org>
> 
> This code is trying to parse PCIe config space of PCIe card connected on
> the other end of link and then is trying to force 5.0 GT/s speed via Target
> Link Speed bits in PCIe Root Port Link Control 2 Register on the local part
> of link if it sees that card supports 5.0 GT/s via Max Link Speed bits in
> Link Capabilities Register.
> 
> The code is incorrect for more reasons:
> - Accessing config space of an endpoint card cannot be done immediately.
>    If the PCIe link is not up, reading vendor/device ID registers will
>    return all ones.
> - Parsing is incomplete, so it can cause issues even for working cards.
> 
> Moreover there is no need to force speed to 5.0 GT/s via Target Link Speed
> bits on PCIe Root Port Link Control 2 Register. Hardware changes speed from
> 2.5 GT/s to 5.0 GT/s autonomously when it is supported.
> 
> Most importantly, this code does not change link speed at all, since
> because after updating Target Link Speed bits on PCIe Root Port Link
> Control 2 Register, it is required to retrain the link, and the code for
> that is completely missing.
> 
> The code was probably needed for making buggy endpoint cards work. Such a
> workaround, though, should be implemented via PCIe subsystem (via quirks,
> for example), as buggy cards could also affect other PCIe controllers.
> 
> Note that this code is fully unrelated to a38x SerDes code and really
> should not have been included in SerDes initialization. Usage of magic
> constants without names and comments made this SerDes code hard to read and
> understand.
> 
> Remove this PCIe application code from low level SerDes code. As this code
> is configuring only 5.0 GT/s part, in the worst case, it could leave buggy
> cards at the initial speed of 2.5 GT/s (if somehow before this change they
> could have been "upgraded" to 5.0 GT/s speed even with missing link
> retraining). Compliant cards which just need longer initialization should
> work better after this change.
> 
> Signed-off-by: Pali Rohár <pali at kernel.org>
> Reviewed-by: Marek Behún <marek.behun at nic.cz>

Reviewed-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan

> ---
>   arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c | 128 +--------------------
>   1 file changed, 1 insertion(+), 127 deletions(-)
> 
> diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
> index a7e45a5550..0445b43def 100644
> --- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
> +++ b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
> @@ -21,10 +21,8 @@ __weak void board_pex_config(void)
>   
>   int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
>   {
> -	u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
> -	    temp_reg, addr, dev_id, ctrl_mode;
>   	enum serdes_type serdes_type;
> -	u32 idx;
> +	u32 idx, tmp;
>   
>   	DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
>   
> @@ -60,132 +58,8 @@ int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
>   
>   	reg_write(SOC_CONTROL_REG1, tmp);
>   
> -	/* Support gen1/gen2 */
> -	DEBUG_INIT_FULL_S("Support gen1/gen2\n");
> -
>   	board_pex_config();
>   
> -	next_busno = 0;
> -	mdelay(150);
> -
> -	for (idx = 0; idx < count; idx++) {
> -		serdes_type = serdes_map[idx].serdes_type;
> -		DEBUG_INIT_FULL_S(" serdes_type=0x");
> -		DEBUG_INIT_FULL_D(serdes_type, 8);
> -		DEBUG_INIT_FULL_S("\n");
> -		DEBUG_INIT_FULL_S(" idx=0x");
> -		DEBUG_INIT_FULL_D(idx, 8);
> -		DEBUG_INIT_FULL_S("\n");
> -
> -		/* Configuration for PEX only */
> -		if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
> -		    (serdes_type != PEX2) && (serdes_type != PEX3))
> -			continue;
> -
> -		if ((serdes_type != PEX0) &&
> -		    ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
> -		     (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
> -			/* for PEX by4 - relevant for the first port only */
> -			continue;
> -		}
> -
> -		pex_idx = serdes_type - PEX0;
> -		tmp = reg_read(PEX_DBG_STATUS_REG(pex_idx));
> -
> -		first_busno = next_busno;
> -		if ((tmp & 0x7f) != 0x7e) {
> -			DEBUG_INIT_S("PCIe, Idx ");
> -			DEBUG_INIT_D(pex_idx, 1);
> -			DEBUG_INIT_S(": detected no link\n");
> -			continue;
> -		}
> -
> -		next_busno++;
> -
> -		/*
> -		 * Read maximum link speed. It must be 0x2 (5.0 GT/s) as this
> -		 * value was set in serdes_power_up_ctrl() function.
> -		 */
> -		temp_pex_reg = reg_read((PEX_CFG_DIRECT_ACCESS
> -					 (pex_idx, PEX_LINK_CAPABILITY_REG)));
> -		temp_pex_reg &= 0xf;
> -		if (temp_pex_reg != 0x2)
> -			continue;
> -
> -		/* Read negotiated link speed */
> -		temp_reg = (reg_read(PEX_CFG_DIRECT_ACCESS(
> -					     pex_idx,
> -					     PEX_LINK_CTRL_STAT_REG)) &
> -			    0xf0000) >> 16;
> -
> -		/* Check if the link established is GEN1 */
> -		DEBUG_INIT_FULL_S
> -			("Checking if the link established is gen1\n");
> -		if (temp_reg != 0x1)
> -			continue;
> -
> -		pex_local_bus_num_set(pex_idx, first_busno);
> -		pex_local_dev_num_set(pex_idx, 1);
> -		DEBUG_INIT_FULL_S("PCIe, Idx ");
> -		DEBUG_INIT_FULL_D(pex_idx, 1);
> -
> -		DEBUG_INIT_S(":** Link is Gen1, check the EP capability\n");
> -		/* link is Gen1, check the EP capability */
> -		addr = pex_config_read(pex_idx, first_busno, 0, 0, 0x34) & 0xff;
> -		DEBUG_INIT_FULL_C("pex_config_read: return addr=0x%x", addr, 4);
> -		if (addr == 0xff) {
> -			DEBUG_INIT_FULL_C
> -				("pex_config_read: return 0xff -->PCIe (%d): Detected No Link.",
> -				 pex_idx, 1);
> -			continue;
> -		}
> -
> -		/* Find start of the PCI Express Capability registers */
> -		while ((pex_config_read(pex_idx, first_busno, 0, 0, addr)
> -			& 0xff) != 0x10) {
> -			addr = (pex_config_read(pex_idx, first_busno, 0,
> -						0, addr) & 0xff00) >> 8;
> -		}
> -
> -		/* Check for Gen2 and above */
> -		if ((pex_config_read(pex_idx, first_busno, 0, 0,
> -				     addr + 0xc) & 0xf) < 0x2) {
> -			DEBUG_INIT_S("PCIe, Idx ");
> -			DEBUG_INIT_D(pex_idx, 1);
> -			DEBUG_INIT_S(": remains Gen1\n");
> -			continue;
> -		}
> -
> -		tmp = reg_read(PEX_LINK_CTRL_STATUS2_REG(pex_idx));
> -		DEBUG_RD_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
> -		tmp &= ~(BIT(0) | BIT(1));
> -		tmp |= BIT(1);	/* Force Target Link Speed to 5.0 GT/s */
> -		tmp |= BIT(6);	/* Select Deemphasize (-3.5d_b) */
> -		reg_write(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
> -		DEBUG_WR_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
> -
> -		/*
> -		 * Enable Auto Speed change. When set, link will issue link
> -		 * speed change to max possible link speed.
> -		 */
> -		tmp = reg_read(PEX_CTRL_REG(pex_idx));
> -		DEBUG_RD_REG(PEX_CTRL_REG(pex_idx), tmp);
> -		tmp |= BIT(10);
> -		reg_write(PEX_CTRL_REG(pex_idx), tmp);
> -		DEBUG_WR_REG(PEX_CTRL_REG(pex_idx), tmp);
> -
> -		/*
> -		 * We need to wait 10ms before reading the PEX_DBG_STATUS_REG
> -		 * in order not to read the status of the former state
> -		 */
> -		mdelay(10);
> -
> -		DEBUG_INIT_S("PCIe, Idx ");
> -		DEBUG_INIT_D(pex_idx, 1);
> -		DEBUG_INIT_S
> -			(": Link upgraded to Gen2 based on client capabilities\n");
> -	}
> -
>   	return MV_OK;
>   }
>   
> 


Viele Grüße,
Stefan

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de


More information about the U-Boot mailing list