diff mbox series

[v2,1/1] arm64: zynqmp: Enable usb3 for k24 som

Message ID 20231215074012.483465-1-neal.frager@amd.com
State New
Headers show
Series [v2,1/1] arm64: zynqmp: Enable usb3 for k24 som | expand

Commit Message

Frager, Neal Dec. 15, 2023, 7:40 a.m. UTC
Currently, the u-boot zynqmp psgtr driver is not connected to the usb dwc3
driver.  Without this, the only way for u-boot to be able to use usb3 is if
the psgtr serdes clocking is already enabled in the psu_init_gpl.c.  This
patch enables the psgtr serdes for usb3 use, so the u-boot dwc3 driver will
work properly on boards based on the k24 som.

In addition, this patch correctly configures mio76 and mio77 as gpio pins
which are used as reset gpio pins on the kd240 starter kit.

This patch is needed for enabling u-boot to load an OS on the kd240
starter kit by either usb3 or the sd card interface connected over the usb3
to sd card bridge.

Signed-off-by: Neal Frager <neal.frager@amd.com>
---
V1->V2:
 - rebased patch to latest u-boot master branch
 - improved git commit message
---
 .../zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c  | 283 +++++++++++++++++-
 1 file changed, 270 insertions(+), 13 deletions(-)

Comments

Michal Simek Dec. 18, 2023, 2 p.m. UTC | #1
On 12/15/23 08:40, Neal Frager wrote:
> Currently, the u-boot zynqmp psgtr driver is not connected to the usb dwc3
> driver.  Without this, the only way for u-boot to be able to use usb3 is if
> the psgtr serdes clocking is already enabled in the psu_init_gpl.c.  This
> patch enables the psgtr serdes for usb3 use, so the u-boot dwc3 driver will
> work properly on boards based on the k24 som.
> 
> In addition, this patch correctly configures mio76 and mio77 as gpio pins
> which are used as reset gpio pins on the kd240 starter kit.
> 
> This patch is needed for enabling u-boot to load an OS on the kd240
> starter kit by either usb3 or the sd card interface connected over the usb3
> to sd card bridge.
> 
> Signed-off-by: Neal Frager <neal.frager@amd.com>
> ---
> V1->V2:
>   - rebased patch to latest u-boot master branch
>   - improved git commit message
> ---
>   .../zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c  | 283 +++++++++++++++++-
>   1 file changed, 270 insertions(+), 13 deletions(-)
> 
> diff --git a/board/xilinx/zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c
> index 166e61431b..591f093752 100644
> --- a/board/xilinx/zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c
> +++ b/board/xilinx/zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c
> @@ -72,6 +72,18 @@ static void dpll_prog(int div2, int ddr_pll_fbdiv, int d_lock_dly,
>   	Xil_Out32(((0xFD1A0000U) + 0x0000002C), pll_ctrl_regval);
>   }
>   
> +static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
> +			   u32 lane2_protocol, u32 lane2_rate,
> +			   u32 lane1_protocol, u32 lane1_rate,
> +			   u32 lane0_protocol, u32 lane0_rate)
> +{
> +	Xil_Out32(0xFD409914, 0xF3);
> +	Xil_Out32(0xFD409940, 0xF3);
> +	Xil_Out32(0xFD409990, 0x20);
> +	Xil_Out32(0xFD409924, 0x37);
> +	return 1;
> +}

 From here

> +
>   static unsigned long psu_pll_init_data(void)
>   {
>   	psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C62U);
> @@ -528,8 +540,8 @@ static unsigned long psu_mio_init_data(void)
>   	psu_mask_write(0xFF180124, 0x000000FEU, 0x00000002U);
>   	psu_mask_write(0xFF180128, 0x000000FEU, 0x00000002U);
>   	psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000002U);
> -	psu_mask_write(0xFF180130, 0x000000FEU, 0x000000C0U);
> -	psu_mask_write(0xFF180134, 0x000000FEU, 0x000000C0U);
> +	psu_mask_write(0xFF180130, 0x000000FEU, 0x00000000U);
> +	psu_mask_write(0xFF180134, 0x000000FEU, 0x00000000U);
>   	psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x50000000U);
>   	psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0x00B02020U);
>   	psu_mask_write(0xFF18020C, 0x00003FFFU, 0x00000FC0U);
> @@ -569,21 +581,16 @@ static unsigned long psu_peripherals_init_data(void)
>   	psu_mask_write(0xFD1A0100, 0x0001807CU, 0x00000000U);
>   	psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
>   	psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
> -	psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
> +	psu_mask_write(0xFF5E0230, 0x00000002U, 0x00000000U);
>   	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
>   	psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
>   	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
> -	psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
> -	psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
> -	psu_mask_write(0xFF180320, 0x33840000U, 0x02840000U);
> -	psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
> -	psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
> -	psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
> +	psu_mask_write(0xFF5E0238, 0x00000080U, 0x00000000U);
>   	psu_mask_write(0xFF5E0238, 0x00000400U, 0x00000000U);
>   	psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
>   	psu_mask_write(0xFF5E0238, 0x00000010U, 0x00000000U);
>   	psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
> -	psu_mask_write(0xFF5E0238, 0x00000004U, 0x00000000U);
> +	psu_mask_write(0xFF5E0238, 0x00000006U, 0x00000000U);
>   	psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
>   	psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
>   	psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
> @@ -591,13 +598,111 @@ static unsigned long psu_peripherals_init_data(void)
>   	psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
>   	psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5DD18U);
>   	psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
> -	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
> +	psu_mask_write(0xFF0A0284, 0x03FFFFFFU, 0x01000000U);
> +	psu_mask_write(0xFF0A0288, 0x03FFFFFFU, 0x01000000U);
> +	psu_mask_write(0xFF0A0014, 0x03FF03FFU, 0x02FF0100U);
>   
>   	mask_delay(1);
> -	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
> +	psu_mask_write(0xFF0A0014, 0x03FF03FFU, 0x02FF0000U);
>   
>   	mask_delay(5);
> -	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
> +	psu_mask_write(0xFF0A0014, 0x03FF03FFU, 0x02FF0100U);
> +
> +	return 1;
> +}

to here that's key part for getting things up and running.
And these are not serdes related configurations.

> +
> +static unsigned long psu_serdes_init_data(void)
> +{
> +	psu_mask_write(0xFD410008, 0x0000001FU, 0x00000008U);
> +	psu_mask_write(0xFD402868, 0x00000080U, 0x00000080U);
> +	psu_mask_write(0xFD40A094, 0x00000010U, 0x00000010U);
> +	psu_mask_write(0xFD40A368, 0x000000FFU, 0x00000038U);
> +	psu_mask_write(0xFD40A36C, 0x00000007U, 0x00000003U);
> +	psu_mask_write(0xFD40A370, 0x000000FFU, 0x000000F4U);
> +	psu_mask_write(0xFD40A374, 0x000000FFU, 0x00000031U);
> +	psu_mask_write(0xFD40A378, 0x000000FFU, 0x00000002U);
> +	psu_mask_write(0xFD40A37C, 0x00000033U, 0x00000030U);
> +	psu_mask_write(0xFD40906C, 0x00000003U, 0x00000003U);
> +	psu_mask_write(0xFD4080F4, 0x00000003U, 0x00000003U);
> +	psu_mask_write(0xFD4090CC, 0x00000020U, 0x00000020U);
> +	psu_mask_write(0xFD401074, 0x00000010U, 0x00000010U);
> +	psu_mask_write(0xFD405074, 0x00000010U, 0x00000010U);
> +	psu_mask_write(0xFD409074, 0x00000010U, 0x00000010U);
> +	psu_mask_write(0xFD40D074, 0x00000010U, 0x00000010U);
> +	psu_mask_write(0xFD401994, 0x00000007U, 0x00000007U);
> +	psu_mask_write(0xFD405994, 0x00000007U, 0x00000007U);
> +	psu_mask_write(0xFD40989C, 0x00000080U, 0x00000080U);
> +	psu_mask_write(0xFD4098F8, 0x000000FFU, 0x0000001AU);
> +	psu_mask_write(0xFD4098FC, 0x000000FFU, 0x0000001AU);
> +	psu_mask_write(0xFD409990, 0x000000FFU, 0x00000010U);
> +	psu_mask_write(0xFD409924, 0x000000FFU, 0x000000FEU);
> +	psu_mask_write(0xFD409928, 0x000000FFU, 0x00000000U);
> +	psu_mask_write(0xFD409900, 0x000000FFU, 0x0000001AU);
> +	psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000000U);
> +	psu_mask_write(0xFD409980, 0x000000FFU, 0x000000FFU);
> +	psu_mask_write(0xFD409914, 0x000000FFU, 0x000000F7U);
> +	psu_mask_write(0xFD409918, 0x00000001U, 0x00000001U);
> +	psu_mask_write(0xFD409940, 0x000000FFU, 0x000000F7U);
> +	psu_mask_write(0xFD409944, 0x00000001U, 0x00000001U);
> +	psu_mask_write(0xFD409994, 0x00000007U, 0x00000007U);
> +	psu_mask_write(0xFD40D994, 0x00000007U, 0x00000007U);
> +	psu_mask_write(0xFD40107C, 0x0000000FU, 0x00000001U);
> +	psu_mask_write(0xFD40507C, 0x0000000FU, 0x00000001U);
> +	psu_mask_write(0xFD40907C, 0x0000000FU, 0x00000001U);
> +	psu_mask_write(0xFD40D07C, 0x0000000FU, 0x00000001U);
> +	psu_mask_write(0xFD4019A4, 0x000000FFU, 0x000000FFU);
> +	psu_mask_write(0xFD401038, 0x00000040U, 0x00000040U);
> +	psu_mask_write(0xFD40102C, 0x00000040U, 0x00000040U);
> +	psu_mask_write(0xFD4059A4, 0x000000FFU, 0x000000FFU);
> +	psu_mask_write(0xFD405038, 0x00000040U, 0x00000040U);
> +	psu_mask_write(0xFD40502C, 0x00000040U, 0x00000040U);
> +	psu_mask_write(0xFD4099A4, 0x000000FFU, 0x000000FFU);
> +	psu_mask_write(0xFD409038, 0x00000040U, 0x00000040U);
> +	psu_mask_write(0xFD40902C, 0x00000040U, 0x00000040U);
> +	psu_mask_write(0xFD40D9A4, 0x000000FFU, 0x000000FFU);
> +	psu_mask_write(0xFD40D038, 0x00000040U, 0x00000040U);
> +	psu_mask_write(0xFD40D02C, 0x00000040U, 0x00000040U);
> +	psu_mask_write(0xFD4019AC, 0x00000003U, 0x00000000U);
> +	psu_mask_write(0xFD4059AC, 0x00000003U, 0x00000000U);
> +	psu_mask_write(0xFD4099AC, 0x00000003U, 0x00000000U);
> +	psu_mask_write(0xFD40D9AC, 0x00000003U, 0x00000000U);
> +	psu_mask_write(0xFD401978, 0x00000010U, 0x00000010U);
> +	psu_mask_write(0xFD405978, 0x00000010U, 0x00000010U);
> +	psu_mask_write(0xFD409978, 0x00000010U, 0x00000010U);
> +	psu_mask_write(0xFD40D978, 0x00000010U, 0x00000010U);
> +
> +	serdes_illcalib(0, 0, 3, 0, 0, 0, 0, 0);
> +	psu_mask_write(0xFD410014, 0x00000007U, 0x00000003U);
> +	return 1;
> +}
> +
> +static unsigned long psu_resetout_init_data(void)
> +{
> +	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
> +	psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
> +	psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000000U);
> +	psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
> +	psu_mask_write(0xFF5E0230, 0x00000002U, 0x00000000U);
> +	psu_mask_write(0xFD1A0100, 0x00010000U, 0x00000000U);
> +	psu_mask_write(0xFD4A0200, 0x00000002U, 0x00000000U);
> +	psu_mask_write(0xFD4A0238, 0x0000000FU, 0x00000000U);
> +	psu_mask_write(0xFE20C200, 0x00023FFFU, 0x00022457U);
> +	psu_mask_write(0xFE20C630, 0x003FFF00U, 0x00000000U);
> +	psu_mask_write(0xFE20C11C, 0x00000600U, 0x00000600U);
> +	psu_mask_write(0xFE20C12C, 0x00004000U, 0x00004000U);
> +	psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U);
> +	mask_poll(0xFD40A3E4, 0x00000010U);
> +
> +	return 1;
> +}
> +
> +static unsigned long psu_resetin_init_data(void)
> +{
> +	psu_mask_write(0xFF5E023C, 0x00000540U, 0x00000540U);
> +	psu_mask_write(0xFF5E0230, 0x00000002U, 0x00000002U);
> +	psu_mask_write(0xFD4A0238, 0x0000000FU, 0x0000000AU);
> +	psu_mask_write(0xFD4A0200, 0x00000002U, 0x00000002U);
> +	psu_mask_write(0xFD1A0100, 0x00010000U, 0x00010000U);
>   
>   	return 1;
>   }
> @@ -911,6 +1016,157 @@ static unsigned long psu_ddr_phybringup_data(void)
>   	return 1;
>   }
>   
> +static int serdes_enb_coarse_saturation(void)
> +{
> +	Xil_Out32(0xFD402094, 0x00000010);
> +	Xil_Out32(0xFD406094, 0x00000010);
> +	Xil_Out32(0xFD40A094, 0x00000010);
> +	Xil_Out32(0xFD40E094, 0x00000010);
> +	return 1;
> +}
> +
> +static int serdes_fixcal_code(void)
> +{
> +	int maskstatus = 1;
> +	unsigned int rdata = 0;
> +	unsigned int match_pmos_code[23];
> +	unsigned int match_nmos_code[23];
> +	unsigned int match_ical_code[7];
> +	unsigned int match_rcal_code[7];
> +	unsigned int p_code = 0;
> +	unsigned int n_code = 0;
> +	unsigned int i_code = 0;
> +	unsigned int r_code = 0;
> +	unsigned int repeat_count = 0;
> +	unsigned int L3_TM_CALIB_DIG20 = 0;
> +	unsigned int L3_TM_CALIB_DIG19 = 0;
> +	unsigned int L3_TM_CALIB_DIG18 = 0;
> +	unsigned int L3_TM_CALIB_DIG16 = 0;
> +	unsigned int L3_TM_CALIB_DIG15 = 0;
> +	unsigned int L3_TM_CALIB_DIG14 = 0;
> +	int i = 0;
> +
> +	rdata = Xil_In32(0xFD40289C);
> +	rdata = rdata & ~0x03;
> +	rdata = rdata | 0x1;
> +	Xil_Out32(0xFD40289C, rdata);
> +	int count = 0;
> +	do {
> +		if (count == 1100000)
> +			break;
> +		rdata = Xil_In32(0xFD402B1C);
> +		count++;
> +	} while ((rdata & 0x0000000E) != 0x0000000E);
> +
> +	for (i = 0; i < 23; i++) {
> +		match_pmos_code[i] = 0;
> +		match_nmos_code[i] = 0;
> +	}
> +	for (i = 0; i < 7; i++) {
> +		match_ical_code[i] = 0;
> +		match_rcal_code[i] = 0;
> +	}
> +
> +	do {
> +		Xil_Out32(0xFD410010, 0x00000000);
> +		Xil_Out32(0xFD410014, 0x00000000);
> +
> +		Xil_Out32(0xFD410010, 0x00000001);
> +		Xil_Out32(0xFD410014, 0x00000000);
> +
> +		maskstatus = mask_poll(0xFD40EF14, 0x2);
> +		if (maskstatus == 0) {
> +			xil_printf("#SERDES initialization timed out\n\r");
> +			return maskstatus;
> +		}
> +
> +		p_code = mask_read(0xFD40EF18, 0xFFFFFFFF);
> +		n_code = mask_read(0xFD40EF1C, 0xFFFFFFFF);
> +		;
> +		i_code = mask_read(0xFD40EF24, 0xFFFFFFFF);
> +		r_code = mask_read(0xFD40EF28, 0xFFFFFFFF);
> +		;
> +
> +		if (p_code >= 0x26 && p_code <= 0x3C)
> +			match_pmos_code[p_code - 0x26] += 1;
> +
> +		if (n_code >= 0x26 && n_code <= 0x3C)
> +			match_nmos_code[n_code - 0x26] += 1;
> +
> +		if (i_code >= 0xC && i_code <= 0x12)
> +			match_ical_code[i_code - 0xC] += 1;
> +
> +		if (r_code >= 0x6 && r_code <= 0xC)
> +			match_rcal_code[r_code - 0x6] += 1;
> +
> +	} while (repeat_count++ < 10);
> +
> +	for (i = 0; i < 23; i++) {
> +		if (match_pmos_code[i] >= match_pmos_code[0]) {
> +			match_pmos_code[0] = match_pmos_code[i];
> +			p_code = 0x26 + i;
> +		}
> +		if (match_nmos_code[i] >= match_nmos_code[0]) {
> +			match_nmos_code[0] = match_nmos_code[i];
> +			n_code = 0x26 + i;
> +		}
> +	}
> +
> +	for (i = 0; i < 7; i++) {
> +		if (match_ical_code[i] >= match_ical_code[0]) {
> +			match_ical_code[0] = match_ical_code[i];
> +			i_code = 0xC + i;
> +		}
> +		if (match_rcal_code[i] >= match_rcal_code[0]) {
> +			match_rcal_code[0] = match_rcal_code[i];
> +			r_code = 0x6 + i;
> +		}
> +	}
> +
> +	L3_TM_CALIB_DIG20 = mask_read(0xFD40EC50, 0xFFFFFFF0);
> +	L3_TM_CALIB_DIG20 = L3_TM_CALIB_DIG20 | 0x8 | ((p_code >> 2) & 0x7);
> +
> +	L3_TM_CALIB_DIG19 = mask_read(0xFD40EC4C, 0xFFFFFF18);
> +	L3_TM_CALIB_DIG19 = L3_TM_CALIB_DIG19 | ((p_code & 0x3) << 6)
> +	    | 0x20 | 0x4 | ((n_code >> 3) & 0x3);
> +
> +	L3_TM_CALIB_DIG18 = mask_read(0xFD40EC48, 0xFFFFFF0F);
> +	L3_TM_CALIB_DIG18 = L3_TM_CALIB_DIG18 | ((n_code & 0x7) << 5) | 0x10;
> +
> +	L3_TM_CALIB_DIG16 = mask_read(0xFD40EC40, 0xFFFFFFF8);
> +	L3_TM_CALIB_DIG16 = L3_TM_CALIB_DIG16 | ((r_code >> 1) & 0x7);
> +
> +	L3_TM_CALIB_DIG15 = mask_read(0xFD40EC3C, 0xFFFFFF30);
> +	L3_TM_CALIB_DIG15 = L3_TM_CALIB_DIG15 | ((r_code & 0x1) << 7)
> +	    | 0x40 | 0x8 | ((i_code >> 1) & 0x7);
> +
> +	L3_TM_CALIB_DIG14 = mask_read(0xFD40EC38, 0xFFFFFF3F);
> +	L3_TM_CALIB_DIG14 = L3_TM_CALIB_DIG14 | ((i_code & 0x1) << 7) | 0x40;
> +
> +	Xil_Out32(0xFD40EC50, L3_TM_CALIB_DIG20);
> +	Xil_Out32(0xFD40EC4C, L3_TM_CALIB_DIG19);
> +	Xil_Out32(0xFD40EC48, L3_TM_CALIB_DIG18);
> +	Xil_Out32(0xFD40EC40, L3_TM_CALIB_DIG16);
> +	Xil_Out32(0xFD40EC3C, L3_TM_CALIB_DIG15);
> +	Xil_Out32(0xFD40EC38, L3_TM_CALIB_DIG14);
> +	return maskstatus;
> +}
> +
> +static int init_serdes(void)
> +{
> +	int status = 1;
> +
> +	status &= psu_resetin_init_data();
> +
> +	status &= serdes_fixcal_code();
> +	status &= serdes_enb_coarse_saturation();
> +
> +	status &= psu_serdes_init_data();
> +	status &= psu_resetout_init_data();
> +
> +	return status;
> +}
> +
>   static void init_peripheral(void)
>   {
>   	psu_mask_write(0xFD5F0018, 0x8000001FU, 0x8000001FU);
> @@ -927,6 +1183,7 @@ int psu_init(void)
>   	status &= psu_ddr_init_data();
>   	status &= psu_ddr_phybringup_data();
>   	status &= psu_peripherals_init_data();
> +	status &= init_serdes();

And regarding serdes initialization itsel.
When you do this.

diff --git a/drivers/phy/phy-zynqmp.c b/drivers/phy/phy-zynqmp.c
index d1288bb17f3c..5d2fe0e4991d 100644
--- a/drivers/phy/phy-zynqmp.c
+++ b/drivers/phy/phy-zynqmp.c
@@ -9,6 +9,8 @@
   * Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
   */

+#define DEBUG
+
  #include <common.h>
  #include <clk-uclass.h>
  #include <dm.h>


And run it. You will see that actually serdes is initialized already with using 
psgtr driver. It means pretty much serdes code is not needed at all.

ZynqMP> usb start
starting USB...
Bus usb@fe200000: psgtr_phy phy@fd400000: Checking name: ref0
psgtr_phy phy@fd400000: ref0 clock not specified (err -61)
psgtr_phy phy@fd400000: Checking name: ref1
psgtr_phy phy@fd400000: ref1 clock not specified (err -61)
psgtr_phy phy@fd400000: Checking name: ref2
psgtr_phy phy@fd400000: clk rate 26000000
psgtr_phy phy@fd400000: Found rate 3
psgtr_phy phy@fd400000: Checking name: ref3
psgtr_phy phy@fd400000: ref3 clock not specified (err -61)
psgtr_phy phy@fd400000: lane 2 (type 0, protocol 3): init done
psgtr_phy phy@fd400000: Waiting for PLL lock
Register 2000440 NbrPorts 2
Starting the controller
USB XHCI 1.00

If that serdes code is required it is pretty much because there is different 
configuration somewhere else.

With USB3.0 and upstream usb stack I see usb not to stable but I see the same 
behavior when u-boot phy driver is not used and sequence above is used.

Anyway I am definitely interested to get MIO values sorted it out because they 
are not correct and should be fixed and pretty much via pinctrl properties at best.
What we should actually do is to take psu_init and simply remove pin 
configuration for all MIOs which are not defined by spec. That would prove that 
our pinctrl setting is complete.

Tejas: Can you please take a look at it?

Thanks,
Michal
diff mbox series

Patch

diff --git a/board/xilinx/zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c
index 166e61431b..591f093752 100644
--- a/board/xilinx/zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c
+++ b/board/xilinx/zynqmp/zynqmp-sm-k24-revA/psu_init_gpl.c
@@ -72,6 +72,18 @@  static void dpll_prog(int div2, int ddr_pll_fbdiv, int d_lock_dly,
 	Xil_Out32(((0xFD1A0000U) + 0x0000002C), pll_ctrl_regval);
 }
 
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+			   u32 lane2_protocol, u32 lane2_rate,
+			   u32 lane1_protocol, u32 lane1_rate,
+			   u32 lane0_protocol, u32 lane0_rate)
+{
+	Xil_Out32(0xFD409914, 0xF3);
+	Xil_Out32(0xFD409940, 0xF3);
+	Xil_Out32(0xFD409990, 0x20);
+	Xil_Out32(0xFD409924, 0x37);
+	return 1;
+}
+
 static unsigned long psu_pll_init_data(void)
 {
 	psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C62U);
@@ -528,8 +540,8 @@  static unsigned long psu_mio_init_data(void)
 	psu_mask_write(0xFF180124, 0x000000FEU, 0x00000002U);
 	psu_mask_write(0xFF180128, 0x000000FEU, 0x00000002U);
 	psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000002U);
-	psu_mask_write(0xFF180130, 0x000000FEU, 0x000000C0U);
-	psu_mask_write(0xFF180134, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180130, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180134, 0x000000FEU, 0x00000000U);
 	psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x50000000U);
 	psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0x00B02020U);
 	psu_mask_write(0xFF18020C, 0x00003FFFU, 0x00000FC0U);
@@ -569,21 +581,16 @@  static unsigned long psu_peripherals_init_data(void)
 	psu_mask_write(0xFD1A0100, 0x0001807CU, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
 	psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
-	psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000002U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
 	psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
 	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
-	psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
-	psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
-	psu_mask_write(0xFF180320, 0x33840000U, 0x02840000U);
-	psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
-	psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
-	psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000080U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00000400U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00000010U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
-	psu_mask_write(0xFF5E0238, 0x00000004U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000006U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
 	psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
 	psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
@@ -591,13 +598,111 @@  static unsigned long psu_peripherals_init_data(void)
 	psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
 	psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5DD18U);
 	psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
-	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+	psu_mask_write(0xFF0A0284, 0x03FFFFFFU, 0x01000000U);
+	psu_mask_write(0xFF0A0288, 0x03FFFFFFU, 0x01000000U);
+	psu_mask_write(0xFF0A0014, 0x03FF03FFU, 0x02FF0100U);
 
 	mask_delay(1);
-	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
+	psu_mask_write(0xFF0A0014, 0x03FF03FFU, 0x02FF0000U);
 
 	mask_delay(5);
-	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+	psu_mask_write(0xFF0A0014, 0x03FF03FFU, 0x02FF0100U);
+
+	return 1;
+}
+
+static unsigned long psu_serdes_init_data(void)
+{
+	psu_mask_write(0xFD410008, 0x0000001FU, 0x00000008U);
+	psu_mask_write(0xFD402868, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40A094, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40A368, 0x000000FFU, 0x00000038U);
+	psu_mask_write(0xFD40A36C, 0x00000007U, 0x00000003U);
+	psu_mask_write(0xFD40A370, 0x000000FFU, 0x000000F4U);
+	psu_mask_write(0xFD40A374, 0x000000FFU, 0x00000031U);
+	psu_mask_write(0xFD40A378, 0x000000FFU, 0x00000002U);
+	psu_mask_write(0xFD40A37C, 0x00000033U, 0x00000030U);
+	psu_mask_write(0xFD40906C, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD4080F4, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD4090CC, 0x00000020U, 0x00000020U);
+	psu_mask_write(0xFD401074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD405074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD409074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40D074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD401994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD405994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40989C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD4098F8, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD4098FC, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD409990, 0x000000FFU, 0x00000010U);
+	psu_mask_write(0xFD409924, 0x000000FFU, 0x000000FEU);
+	psu_mask_write(0xFD409928, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD409900, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD409980, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD409914, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD409918, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409940, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD409944, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40D994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40107C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40507C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40907C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40D07C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD4019A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD401038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40102C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4059A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD405038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40502C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4099A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD409038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40902C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40D9A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD40D038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40D02C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4019AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD4059AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD4099AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD40D9AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD401978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD405978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD409978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40D978, 0x00000010U, 0x00000010U);
+
+	serdes_illcalib(0, 0, 3, 0, 0, 0, 0, 0);
+	psu_mask_write(0xFD410014, 0x00000007U, 0x00000003U);
+	return 1;
+}
+
+static unsigned long psu_resetout_init_data(void)
+{
+	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+	psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000002U, 0x00000000U);
+	psu_mask_write(0xFD1A0100, 0x00010000U, 0x00000000U);
+	psu_mask_write(0xFD4A0200, 0x00000002U, 0x00000000U);
+	psu_mask_write(0xFD4A0238, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFE20C200, 0x00023FFFU, 0x00022457U);
+	psu_mask_write(0xFE20C630, 0x003FFF00U, 0x00000000U);
+	psu_mask_write(0xFE20C11C, 0x00000600U, 0x00000600U);
+	psu_mask_write(0xFE20C12C, 0x00004000U, 0x00004000U);
+	psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U);
+	mask_poll(0xFD40A3E4, 0x00000010U);
+
+	return 1;
+}
+
+static unsigned long psu_resetin_init_data(void)
+{
+	psu_mask_write(0xFF5E023C, 0x00000540U, 0x00000540U);
+	psu_mask_write(0xFF5E0230, 0x00000002U, 0x00000002U);
+	psu_mask_write(0xFD4A0238, 0x0000000FU, 0x0000000AU);
+	psu_mask_write(0xFD4A0200, 0x00000002U, 0x00000002U);
+	psu_mask_write(0xFD1A0100, 0x00010000U, 0x00010000U);
 
 	return 1;
 }
@@ -911,6 +1016,157 @@  static unsigned long psu_ddr_phybringup_data(void)
 	return 1;
 }
 
+static int serdes_enb_coarse_saturation(void)
+{
+	Xil_Out32(0xFD402094, 0x00000010);
+	Xil_Out32(0xFD406094, 0x00000010);
+	Xil_Out32(0xFD40A094, 0x00000010);
+	Xil_Out32(0xFD40E094, 0x00000010);
+	return 1;
+}
+
+static int serdes_fixcal_code(void)
+{
+	int maskstatus = 1;
+	unsigned int rdata = 0;
+	unsigned int match_pmos_code[23];
+	unsigned int match_nmos_code[23];
+	unsigned int match_ical_code[7];
+	unsigned int match_rcal_code[7];
+	unsigned int p_code = 0;
+	unsigned int n_code = 0;
+	unsigned int i_code = 0;
+	unsigned int r_code = 0;
+	unsigned int repeat_count = 0;
+	unsigned int L3_TM_CALIB_DIG20 = 0;
+	unsigned int L3_TM_CALIB_DIG19 = 0;
+	unsigned int L3_TM_CALIB_DIG18 = 0;
+	unsigned int L3_TM_CALIB_DIG16 = 0;
+	unsigned int L3_TM_CALIB_DIG15 = 0;
+	unsigned int L3_TM_CALIB_DIG14 = 0;
+	int i = 0;
+
+	rdata = Xil_In32(0xFD40289C);
+	rdata = rdata & ~0x03;
+	rdata = rdata | 0x1;
+	Xil_Out32(0xFD40289C, rdata);
+	int count = 0;
+	do {
+		if (count == 1100000)
+			break;
+		rdata = Xil_In32(0xFD402B1C);
+		count++;
+	} while ((rdata & 0x0000000E) != 0x0000000E);
+
+	for (i = 0; i < 23; i++) {
+		match_pmos_code[i] = 0;
+		match_nmos_code[i] = 0;
+	}
+	for (i = 0; i < 7; i++) {
+		match_ical_code[i] = 0;
+		match_rcal_code[i] = 0;
+	}
+
+	do {
+		Xil_Out32(0xFD410010, 0x00000000);
+		Xil_Out32(0xFD410014, 0x00000000);
+
+		Xil_Out32(0xFD410010, 0x00000001);
+		Xil_Out32(0xFD410014, 0x00000000);
+
+		maskstatus = mask_poll(0xFD40EF14, 0x2);
+		if (maskstatus == 0) {
+			xil_printf("#SERDES initialization timed out\n\r");
+			return maskstatus;
+		}
+
+		p_code = mask_read(0xFD40EF18, 0xFFFFFFFF);
+		n_code = mask_read(0xFD40EF1C, 0xFFFFFFFF);
+		;
+		i_code = mask_read(0xFD40EF24, 0xFFFFFFFF);
+		r_code = mask_read(0xFD40EF28, 0xFFFFFFFF);
+		;
+
+		if (p_code >= 0x26 && p_code <= 0x3C)
+			match_pmos_code[p_code - 0x26] += 1;
+
+		if (n_code >= 0x26 && n_code <= 0x3C)
+			match_nmos_code[n_code - 0x26] += 1;
+
+		if (i_code >= 0xC && i_code <= 0x12)
+			match_ical_code[i_code - 0xC] += 1;
+
+		if (r_code >= 0x6 && r_code <= 0xC)
+			match_rcal_code[r_code - 0x6] += 1;
+
+	} while (repeat_count++ < 10);
+
+	for (i = 0; i < 23; i++) {
+		if (match_pmos_code[i] >= match_pmos_code[0]) {
+			match_pmos_code[0] = match_pmos_code[i];
+			p_code = 0x26 + i;
+		}
+		if (match_nmos_code[i] >= match_nmos_code[0]) {
+			match_nmos_code[0] = match_nmos_code[i];
+			n_code = 0x26 + i;
+		}
+	}
+
+	for (i = 0; i < 7; i++) {
+		if (match_ical_code[i] >= match_ical_code[0]) {
+			match_ical_code[0] = match_ical_code[i];
+			i_code = 0xC + i;
+		}
+		if (match_rcal_code[i] >= match_rcal_code[0]) {
+			match_rcal_code[0] = match_rcal_code[i];
+			r_code = 0x6 + i;
+		}
+	}
+
+	L3_TM_CALIB_DIG20 = mask_read(0xFD40EC50, 0xFFFFFFF0);
+	L3_TM_CALIB_DIG20 = L3_TM_CALIB_DIG20 | 0x8 | ((p_code >> 2) & 0x7);
+
+	L3_TM_CALIB_DIG19 = mask_read(0xFD40EC4C, 0xFFFFFF18);
+	L3_TM_CALIB_DIG19 = L3_TM_CALIB_DIG19 | ((p_code & 0x3) << 6)
+	    | 0x20 | 0x4 | ((n_code >> 3) & 0x3);
+
+	L3_TM_CALIB_DIG18 = mask_read(0xFD40EC48, 0xFFFFFF0F);
+	L3_TM_CALIB_DIG18 = L3_TM_CALIB_DIG18 | ((n_code & 0x7) << 5) | 0x10;
+
+	L3_TM_CALIB_DIG16 = mask_read(0xFD40EC40, 0xFFFFFFF8);
+	L3_TM_CALIB_DIG16 = L3_TM_CALIB_DIG16 | ((r_code >> 1) & 0x7);
+
+	L3_TM_CALIB_DIG15 = mask_read(0xFD40EC3C, 0xFFFFFF30);
+	L3_TM_CALIB_DIG15 = L3_TM_CALIB_DIG15 | ((r_code & 0x1) << 7)
+	    | 0x40 | 0x8 | ((i_code >> 1) & 0x7);
+
+	L3_TM_CALIB_DIG14 = mask_read(0xFD40EC38, 0xFFFFFF3F);
+	L3_TM_CALIB_DIG14 = L3_TM_CALIB_DIG14 | ((i_code & 0x1) << 7) | 0x40;
+
+	Xil_Out32(0xFD40EC50, L3_TM_CALIB_DIG20);
+	Xil_Out32(0xFD40EC4C, L3_TM_CALIB_DIG19);
+	Xil_Out32(0xFD40EC48, L3_TM_CALIB_DIG18);
+	Xil_Out32(0xFD40EC40, L3_TM_CALIB_DIG16);
+	Xil_Out32(0xFD40EC3C, L3_TM_CALIB_DIG15);
+	Xil_Out32(0xFD40EC38, L3_TM_CALIB_DIG14);
+	return maskstatus;
+}
+
+static int init_serdes(void)
+{
+	int status = 1;
+
+	status &= psu_resetin_init_data();
+
+	status &= serdes_fixcal_code();
+	status &= serdes_enb_coarse_saturation();
+
+	status &= psu_serdes_init_data();
+	status &= psu_resetout_init_data();
+
+	return status;
+}
+
 static void init_peripheral(void)
 {
 	psu_mask_write(0xFD5F0018, 0x8000001FU, 0x8000001FU);
@@ -927,6 +1183,7 @@  int psu_init(void)
 	status &= psu_ddr_init_data();
 	status &= psu_ddr_phybringup_data();
 	status &= psu_peripherals_init_data();
+	status &= init_serdes();
 	init_peripheral();
 
 	status &= psu_afi_config();