230 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			230 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  * Xilinx ZynqMP SoC Tap Delay Programming
 | |
|  *
 | |
|  * Copyright (C) 2018 Xilinx, Inc.
 | |
|  */
 | |
| 
 | |
| #include <common.h>
 | |
| #include <asm/arch/sys_proto.h>
 | |
| 
 | |
| #define SD_DLL_CTRL			0xFF180358
 | |
| #define SD_ITAP_DLY			0xFF180314
 | |
| #define SD_OTAP_DLY			0xFF180318
 | |
| #define SD0_DLL_RST_MASK		0x00000004
 | |
| #define SD0_DLL_RST			0x00000004
 | |
| #define SD1_DLL_RST_MASK		0x00040000
 | |
| #define SD1_DLL_RST			0x00040000
 | |
| #define SD0_ITAPCHGWIN_MASK		0x00000200
 | |
| #define SD0_ITAPCHGWIN			0x00000200
 | |
| #define SD1_ITAPCHGWIN_MASK		0x02000000
 | |
| #define SD1_ITAPCHGWIN			0x02000000
 | |
| #define SD0_ITAPDLYENA_MASK		0x00000100
 | |
| #define SD0_ITAPDLYENA			0x00000100
 | |
| #define SD1_ITAPDLYENA_MASK		0x01000000
 | |
| #define SD1_ITAPDLYENA			0x01000000
 | |
| #define SD0_ITAPDLYSEL_MASK		0x000000FF
 | |
| #define SD0_ITAPDLYSEL_HSD		0x00000015
 | |
| #define SD0_ITAPDLYSEL_SD_DDR50		0x0000003D
 | |
| #define SD0_ITAPDLYSEL_MMC_DDR50	0x00000012
 | |
| 
 | |
| #define SD1_ITAPDLYSEL_MASK		0x00FF0000
 | |
| #define SD1_ITAPDLYSEL_HSD		0x00150000
 | |
| #define SD1_ITAPDLYSEL_SD_DDR50		0x003D0000
 | |
| #define SD1_ITAPDLYSEL_MMC_DDR50	0x00120000
 | |
| 
 | |
| #define SD0_OTAPDLYSEL_MASK		0x0000003F
 | |
| #define SD0_OTAPDLYSEL_MMC_HSD		0x00000006
 | |
| #define SD0_OTAPDLYSEL_SD_HSD		0x00000005
 | |
| #define SD0_OTAPDLYSEL_SDR50		0x00000003
 | |
| #define SD0_OTAPDLYSEL_SDR104_B0	0x00000003
 | |
| #define SD0_OTAPDLYSEL_SDR104_B2	0x00000002
 | |
| #define SD0_OTAPDLYSEL_SD_DDR50		0x00000004
 | |
| #define SD0_OTAPDLYSEL_MMC_DDR50	0x00000006
 | |
| 
 | |
| #define SD1_OTAPDLYSEL_MASK		0x003F0000
 | |
| #define SD1_OTAPDLYSEL_MMC_HSD		0x00060000
 | |
| #define SD1_OTAPDLYSEL_SD_HSD		0x00050000
 | |
| #define SD1_OTAPDLYSEL_SDR50		0x00030000
 | |
| #define SD1_OTAPDLYSEL_SDR104_B0	0x00030000
 | |
| #define SD1_OTAPDLYSEL_SDR104_B2	0x00020000
 | |
| #define SD1_OTAPDLYSEL_SD_DDR50		0x00040000
 | |
| #define SD1_OTAPDLYSEL_MMC_DDR50	0x00060000
 | |
| 
 | |
| #define MMC_BANK2		0x2
 | |
| 
 | |
| #define MMC_TIMING_UHS_SDR25		1
 | |
| #define MMC_TIMING_UHS_SDR50		2
 | |
| #define MMC_TIMING_UHS_SDR104		3
 | |
| #define MMC_TIMING_UHS_DDR50		4
 | |
| #define MMC_TIMING_MMC_HS200		5
 | |
| #define MMC_TIMING_SD_HS		6
 | |
| #define MMC_TIMING_MMC_DDR52		7
 | |
| #define MMC_TIMING_MMC_HS		8
 | |
| 
 | |
| void zynqmp_dll_reset(u8 deviceid)
 | |
| {
 | |
| 	/* Issue DLL Reset */
 | |
| 	if (deviceid == 0)
 | |
| 		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
 | |
| 				  SD0_DLL_RST);
 | |
| 	else
 | |
| 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
 | |
| 				  SD1_DLL_RST);
 | |
| 
 | |
| 	mdelay(1);
 | |
| 
 | |
| 	/* Release DLL Reset */
 | |
| 	if (deviceid == 0)
 | |
| 		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
 | |
| 	else
 | |
| 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
 | |
| }
 | |
| 
 | |
| static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank)
 | |
| {
 | |
| 	if (deviceid == 0) {
 | |
| 		/* Program OTAP */
 | |
| 		if (bank == MMC_BANK2)
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
 | |
| 					  SD0_OTAPDLYSEL_SDR104_B2);
 | |
| 		else
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
 | |
| 					  SD0_OTAPDLYSEL_SDR104_B0);
 | |
| 	} else {
 | |
| 		/* Program OTAP */
 | |
| 		if (bank == MMC_BANK2)
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
 | |
| 					  SD1_OTAPDLYSEL_SDR104_B2);
 | |
| 		else
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
 | |
| 					  SD1_OTAPDLYSEL_SDR104_B0);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank)
 | |
| {
 | |
| 	if (deviceid == 0) {
 | |
| 		/* Program ITAP */
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
 | |
| 				  SD0_ITAPCHGWIN);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
 | |
| 				  SD0_ITAPDLYENA);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
 | |
| 				  SD0_ITAPDLYSEL_HSD);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
 | |
| 		/* Program OTAP */
 | |
| 		if (timing == MMC_TIMING_MMC_HS)
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
 | |
| 					  SD0_OTAPDLYSEL_MMC_HSD);
 | |
| 		else
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
 | |
| 					  SD0_OTAPDLYSEL_SD_HSD);
 | |
| 	} else {
 | |
| 		/* Program ITAP */
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
 | |
| 				  SD1_ITAPCHGWIN);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
 | |
| 				  SD1_ITAPDLYENA);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
 | |
| 				  SD1_ITAPDLYSEL_HSD);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
 | |
| 		/* Program OTAP */
 | |
| 		if (timing == MMC_TIMING_MMC_HS)
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
 | |
| 					  SD1_OTAPDLYSEL_MMC_HSD);
 | |
| 		else
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
 | |
| 					  SD1_OTAPDLYSEL_SD_HSD);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank)
 | |
| {
 | |
| 	if (deviceid == 0) {
 | |
| 		/* Program ITAP */
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
 | |
| 				  SD0_ITAPCHGWIN);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
 | |
| 				  SD0_ITAPDLYENA);
 | |
| 		if (timing == MMC_TIMING_UHS_DDR50)
 | |
| 			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
 | |
| 					  SD0_ITAPDLYSEL_SD_DDR50);
 | |
| 		else
 | |
| 			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
 | |
| 					  SD0_ITAPDLYSEL_MMC_DDR50);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
 | |
| 		/* Program OTAP */
 | |
| 		if (timing == MMC_TIMING_UHS_DDR50)
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
 | |
| 					  SD0_OTAPDLYSEL_SD_DDR50);
 | |
| 		else
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
 | |
| 					  SD0_OTAPDLYSEL_MMC_DDR50);
 | |
| 	} else {
 | |
| 		/* Program ITAP */
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
 | |
| 				  SD1_ITAPCHGWIN);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
 | |
| 				  SD1_ITAPDLYENA);
 | |
| 		if (timing == MMC_TIMING_UHS_DDR50)
 | |
| 			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
 | |
| 					  SD1_ITAPDLYSEL_SD_DDR50);
 | |
| 		else
 | |
| 			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
 | |
| 					  SD1_ITAPDLYSEL_MMC_DDR50);
 | |
| 		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
 | |
| 		/* Program OTAP */
 | |
| 		if (timing == MMC_TIMING_UHS_DDR50)
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
 | |
| 					  SD1_OTAPDLYSEL_SD_DDR50);
 | |
| 		else
 | |
| 			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
 | |
| 					  SD1_OTAPDLYSEL_MMC_DDR50);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank)
 | |
| {
 | |
| 	if (deviceid == 0) {
 | |
| 		/* Program OTAP */
 | |
| 		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
 | |
| 				  SD0_OTAPDLYSEL_SDR50);
 | |
| 	} else {
 | |
| 		/* Program OTAP */
 | |
| 		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
 | |
| 				  SD1_OTAPDLYSEL_SDR50);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank)
 | |
| {
 | |
| 	if (deviceid == 0)
 | |
| 		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
 | |
| 				  SD0_DLL_RST);
 | |
| 	else
 | |
| 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
 | |
| 				  SD1_DLL_RST);
 | |
| 
 | |
| 	switch (timing) {
 | |
| 	case MMC_TIMING_UHS_SDR25:
 | |
| 		arasan_zynqmp_tap_hs(deviceid, timing, bank);
 | |
| 		break;
 | |
| 	case MMC_TIMING_UHS_SDR50:
 | |
| 		arasan_zynqmp_tap_sdr50(deviceid, timing, bank);
 | |
| 		break;
 | |
| 	case MMC_TIMING_UHS_SDR104:
 | |
| 	case MMC_TIMING_MMC_HS200:
 | |
| 		arasan_zynqmp_tap_sdr104(deviceid, timing, bank);
 | |
| 		break;
 | |
| 	case MMC_TIMING_UHS_DDR50:
 | |
| 		arasan_zynqmp_tap_ddr50(deviceid, timing, bank);
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	if (deviceid == 0)
 | |
| 		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
 | |
| 	else
 | |
| 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
 | |
| }
 |