[U-Boot] [RESEND PATCH v3 1/7] armv8: lsch3: Add serdes and DDR voltage setup

York Sun york.sun at nxp.com
Thu Sep 14 21:02:35 UTC 2017


You have a lot of magic numbers and delays. See inline comments.

On 09/03/2017 11:24 PM, Rajesh Bhagat wrote:
> Adds SERDES voltage and reset SERDES lanes API and makes
> enable/disable DDR controller support 0.9V API common.
> 
> Signed-off-by: Ashish Kumar <Ashish.Kumar at nxp.com>
> Signed-off-by: Rajesh Bhagat <rajesh.bhagat at nxp.com>
> ---
> Changes in v3:
>   Restructured LS1088A VID support to use common VID driver
>   Cosmetic review comments fixed
>   Added __iomem for accessing registers
> 
> Changes in v2:
>   Checkpatch errors fixed
> 
>   .../cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c    | 274 +++++++++++++++++++++
>   arch/arm/cpu/armv8/fsl-layerscape/soc.c            |  34 +--
>   .../include/asm/arch-fsl-layerscape/fsl_serdes.h   |   2 +-
>   .../include/asm/arch-fsl-layerscape/immap_lsch3.h  |  34 +++
>   arch/arm/include/asm/arch-fsl-layerscape/soc.h     |   1 +
>   5 files changed, 327 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
> index 179cac6..39f2cdf 100644
> --- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
> +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
> @@ -158,6 +158,280 @@ void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask,
>   	serdes_prtcl_map[NONE] = 1;
>   }
>   
> +__weak int get_serdes_volt(void)
> +{
> +	return -1;
> +}
> +
> +__weak int set_serdes_volt(int svdd)
> +{
> +	return -1;
> +}
> +
> +int setup_serdes_volt(u32 svdd)
> +{
> +	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
> +	struct ccsr_serdes __iomem *serdes1_base;
> +	u32 cfg_rcwsrds1 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]);
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	struct ccsr_serdes __iomem *serdes2_base;
> +	u32 cfg_rcwsrds2 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
> +#endif
> +	u32 cfg_tmp, reg = 0;
> +	int svdd_cur, svdd_tar;
> +	int ret = 1;
> +	int i;
> +
> +	/* Only support switch SVDD to 900mV */
> +	if (svdd != 900)
> +		return -1;
> +
> +	/* Scale up to the LTC resolution is 1/4096V */
> +	svdd = (svdd * 4096) / 1000;
> +
> +	svdd_tar = svdd;
> +	svdd_cur = get_serdes_volt();
> +	if (svdd_cur < 0)
> +		return -EINVAL;
> +
> +	debug("%s: current SVDD: %x; target SVDD: %x\n",
> +	      __func__, svdd_cur, svdd_tar);
> +	if (svdd_cur == svdd_tar)
> +		return 0;
> +
> +	serdes1_base = (void *)CONFIG_SYS_FSL_LSCH3_SERDES_ADDR;
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	serdes2_base =  (void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x10000);
> +#endif
> +
> +	/* Put the all enabled lanes in reset */
> +#ifdef CONFIG_SYS_FSL_SRDS_1
> +	cfg_tmp = cfg_rcwsrds1 & FSL_CHASSIS3_SRDS1_PRTCL_MASK;
> +	cfg_tmp >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
> +
> +	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
> +		reg = in_le32(&serdes1_base->lane[i].gcr0);
> +		reg &= 0xFF9FFFFF;
> +		out_le32(&serdes1_base->lane[i].gcr0, reg);
> +	}
> +#endif

Please use local macros instead of magic numbers here and below.

> +
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	cfg_tmp = cfg_rcwsrds2 & FSL_CHASSIS3_SRDS2_PRTCL_MASK;
> +	cfg_tmp >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT;
> +
> +	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
> +		reg = in_le32(&serdes2_base->lane[i].gcr0);
> +		reg &= 0xFF9FFFFF;
> +		out_le32(&serdes2_base->lane[i].gcr0, reg);
> +	}
> +#endif
> +
> +	/* Put the all enabled PLL in reset */
> +#ifdef CONFIG_SYS_FSL_SRDS_1
> +	cfg_tmp = cfg_rcwsrds1 & 0x3;
> +	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
> +		reg = in_le32(&serdes1_base->bank[i].rstctl);
> +		reg &= 0xFFFFFFBF;
> +		reg |= 0x10000000;
> +		out_le32(&serdes1_base->bank[i].rstctl, reg);
> +	}
> +	udelay(1);
> +
> +	reg = in_le32(&serdes1_base->bank[i].rstctl);
> +	reg &= 0xFFFFFF1F;
> +	out_le32(&serdes1_base->bank[i].rstctl, reg);
> +#endif
> +
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	cfg_tmp = cfg_rcwsrds1 & 0xC;
> +	cfg_tmp >>= 2;
> +	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
> +		reg = in_le32(&serdes2_base->bank[i].rstctl);
> +		reg &= 0xFFFFFFBF;
> +		reg |= 0x10000000;
> +		out_le32(&serdes2_base->bank[i].rstctl, reg);
> +	}
> +	udelay(1);

What's this delay for?

> +
> +	reg = in_le32(&serdes2_base->bank[i].rstctl);
> +	reg &= 0xFFFFFF1F;
> +	out_le32(&serdes2_base->bank[i].rstctl, reg);
> +#endif
> +
> +	/* Put the Rx/Tx calibration into reset */
> +#ifdef CONFIG_SYS_FSL_SRDS_1
> +	reg = in_le32(&serdes1_base->srdstcalcr);
> +	reg &= 0xF7FFFFFF;
> +	out_le32(&serdes1_base->srdstcalcr, reg);
> +	reg = in_le32(&serdes1_base->srdsrcalcr);
> +	reg &= 0xF7FFFFFF;
> +	out_le32(&serdes1_base->srdsrcalcr, reg);
> +#endif
> +
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	reg = in_le32(&serdes2_base->srdstcalcr);
> +	reg &= 0xF7FFFFFF;
> +	out_le32(&serdes2_base->srdstcalcr, reg);
> +	reg = in_le32(&serdes2_base->srdsrcalcr);
> +	reg &= 0xF7FFFFFF;
> +	out_le32(&serdes2_base->srdsrcalcr, reg);
> +#endif
> +
> +	ret = set_serdes_volt(svdd);
> +	if (ret < 0) {
> +		printf("could not change SVDD\n");
> +		ret = -1;
> +	}
> +
> +	/* For each PLL that’s not disabled via RCW enable the SERDES */
> +#ifdef CONFIG_SYS_FSL_SRDS_1
> +	cfg_tmp = cfg_rcwsrds1 & 0x3;
> +	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
> +		reg = in_le32(&serdes1_base->bank[i].rstctl);
> +		reg |= 0x00000020;
> +		out_le32(&serdes1_base->bank[i].rstctl, reg);
> +		udelay(1);

Why delay here?

> +
> +		reg = in_le32(&serdes1_base->bank[i].rstctl);
> +		reg |= 0x00000080;
> +		out_le32(&serdes1_base->bank[i].rstctl, reg);
> +		udelay(1);

Here.

> +		/* Take the Rx/Tx calibration out of reset */
> +		if (!(cfg_tmp == 0x3 && i == 1)) {
> +			udelay(1);
> +			reg = in_le32(&serdes1_base->srdstcalcr);
> +			reg |= 0x08000000;
> +			out_le32(&serdes1_base->srdstcalcr, reg);
> +			reg = in_le32(&serdes1_base->srdsrcalcr);
> +			reg |= 0x08000000;
> +			out_le32(&serdes1_base->srdsrcalcr, reg);
> +		}
> +		udelay(1);

Why delay here?

> +	}
> +#endif
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	cfg_tmp = cfg_rcwsrds1 & 0xC;
> +	cfg_tmp >>= 2;
> +	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
> +		reg = in_le32(&serdes2_base->bank[i].rstctl);
> +		reg |= 0x00000020;
> +		out_le32(&serdes2_base->bank[i].rstctl, reg);
> +		udelay(1);
> +
> +		reg = in_le32(&serdes2_base->bank[i].rstctl);
> +		reg |= 0x00000080;
> +		out_le32(&serdes2_base->bank[i].rstctl, reg);
> +		udelay(1);
> +
> +		/* Take the Rx/Tx calibration out of reset */
> +		if (!(cfg_tmp == 0x3 && i == 1)) {
> +			udelay(1);
> +			reg = in_le32(&serdes2_base->srdstcalcr);
> +			reg |= 0x08000000;
> +			out_le32(&serdes2_base->srdstcalcr, reg);
> +			reg = in_le32(&serdes2_base->srdsrcalcr);
> +			reg |= 0x08000000;
> +			out_le32(&serdes2_base->srdsrcalcr, reg);
> +		}
> +		udelay(1);
> +	}
> +#endif

You have many duplicated code. Use functions or macros.

> +
> +	/* Wait for at atleast 625us, ensure the PLLs being reset are locked */
> +	udelay(800);

You said 625us, but using 800.

> +
> +#ifdef CONFIG_SYS_FSL_SRDS_1
> +	cfg_tmp = cfg_rcwsrds1 & 0x3;
> +	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
> +		/* if the PLL is not locked, set RST_ERR */
> +		reg = in_le32(&serdes1_base->bank[i].pllcr0);
> +		if (!((reg >> 23) & 0x1)) {
> +			reg = in_le32(&serdes1_base->bank[i].rstctl);
> +			reg |= 0x20000000;
> +			out_le32(&serdes1_base->bank[i].rstctl, reg);
> +		} else {
> +			udelay(1);
> +			reg = in_le32(&serdes1_base->bank[i].rstctl);
> +			reg &= 0xFFFFFFEF;
> +			reg |= 0x00000040;
> +			out_le32(&serdes1_base->bank[i].rstctl, reg);
> +			udelay(1);
> +		}
> +	}
> +#endif
> +
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	cfg_tmp = cfg_rcwsrds1 & 0xC;
> +	cfg_tmp >>= 2;
> +
> +	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
> +		reg = in_le32(&serdes2_base->bank[i].pllcr0);
> +		if (!((reg >> 23) & 0x1)) {
> +			reg = in_le32(&serdes2_base->bank[i].rstctl);
> +			reg |= 0x20000000;
> +			out_le32(&serdes2_base->bank[i].rstctl, reg);
> +		} else {
> +			udelay(1);
> +			reg = in_le32(&serdes2_base->bank[i].rstctl);
> +			reg &= 0xFFFFFFEF;
> +			reg |= 0x00000040;
> +			out_le32(&serdes2_base->bank[i].rstctl, reg);
> +			udelay(1);
> +		}
> +	}
> +#endif
> +	/* Take the all enabled lanes out of reset */
> +#ifdef CONFIG_SYS_FSL_SRDS_1
> +	cfg_tmp = cfg_rcwsrds1 & FSL_CHASSIS3_SRDS1_PRTCL_MASK;
> +	cfg_tmp >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
> +
> +	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
> +		reg = in_le32(&serdes1_base->lane[i].gcr0);
> +		reg |= 0x00600000;
> +		out_le32(&serdes1_base->lane[i].gcr0, reg);
> +	}
> +#endif
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	cfg_tmp = cfg_rcwsrds2 & FSL_CHASSIS3_SRDS2_PRTCL_MASK;
> +	cfg_tmp >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT;
> +
> +	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
> +		reg = in_le32(&serdes2_base->lane[i].gcr0);
> +		reg |= 0x00600000;
> +		out_le32(&serdes2_base->lane[i].gcr0, reg);
> +	}
> +#endif
> +
> +	/* For each PLL being reset, and achieved PLL lock set RST_DONE */
> +#ifdef CONFIG_SYS_FSL_SRDS_1
> +	cfg_tmp = cfg_rcwsrds1 & 0x3;
> +	for (i = 0; i < 2; i++) {
> +		reg = in_le32(&serdes1_base->bank[i].pllcr0);
> +		if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
> +			reg = in_le32(&serdes1_base->bank[i].rstctl);
> +			reg |= 0x40000000;
> +			out_le32(&serdes1_base->bank[i].rstctl, reg);
> +		}
> +	}
> +#endif
> +#ifdef CONFIG_SYS_FSL_SRDS_2
> +	cfg_tmp = cfg_rcwsrds1 & 0xC;
> +	cfg_tmp >>= 2;
> +
> +	for (i = 0; i < 2; i++) {
> +		reg = in_le32(&serdes2_base->bank[i].pllcr0);
> +		if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
> +			reg = in_le32(&serdes2_base->bank[i].rstctl);
> +			reg |= 0x40000000;
> +			out_le32(&serdes2_base->bank[i].rstctl, reg);
> +		}
> +	}
> +#endif
> +
> +	return ret;
> +}
> +
>   void fsl_serdes_init(void)
>   {
>   #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
> diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
> index 83e2871..4e96c7b 100644
> --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
> +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
> @@ -404,23 +404,6 @@ static int setup_core_volt(u32 vdd)
>   	return board_setup_core_volt(vdd);
>   }
>   
> -#ifdef CONFIG_SYS_FSL_DDR
> -static void ddr_enable_0v9_volt(bool en)
> -{
> -	struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
> -	u32 tmp;
> -
> -	tmp = ddr_in32(&ddr->ddr_cdr1);
> -
> -	if (en)
> -		tmp |= DDR_CDR1_V0PT9_EN;
> -	else
> -		tmp &= ~DDR_CDR1_V0PT9_EN;
> -
> -	ddr_out32(&ddr->ddr_cdr1, tmp);
> -}
> -#endif
> -
>   int setup_chip_volt(void)
>   {
>   	int vdd;
> @@ -485,6 +468,23 @@ void fsl_lsch2_early_init_f(void)
>   }
>   #endif
>   
> +#ifdef CONFIG_SYS_FSL_DDR
> +void ddr_enable_0v9_volt(bool en)
> +{
> +	struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
> +	u32 tmp;
> +
> +	tmp = ddr_in32(&ddr->ddr_cdr1);
> +
> +	if (en)
> +		tmp |= DDR_CDR1_V0PT9_EN;
> +	else
> +		tmp &= ~DDR_CDR1_V0PT9_EN;
> +
> +	ddr_out32(&ddr->ddr_cdr1, tmp);
> +}
> +#endif
> +


I lost track. When do you use 0.9v for DDR?

York


More information about the U-Boot mailing list