1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Xilinx ZynqMP SoC Tap Delay Programming
4  *
5  * Copyright (C) 2018 Xilinx, Inc.
6  */
7 
8 #include <common.h>
9 #include <zynqmp_tap_delay.h>
10 #include <asm/arch/sys_proto.h>
11 #include <linux/delay.h>
12 #include <mmc.h>
13 
14 #define SD_DLL_CTRL			0xFF180358
15 #define SD_ITAP_DLY			0xFF180314
16 #define SD_OTAP_DLY			0xFF180318
17 #define SD0_DLL_RST_MASK		0x00000004
18 #define SD0_DLL_RST			0x00000004
19 #define SD1_DLL_RST_MASK		0x00040000
20 #define SD1_DLL_RST			0x00040000
21 #define SD0_ITAPCHGWIN_MASK		0x00000200
22 #define SD0_ITAPCHGWIN			0x00000200
23 #define SD1_ITAPCHGWIN_MASK		0x02000000
24 #define SD1_ITAPCHGWIN			0x02000000
25 #define SD0_ITAPDLYENA_MASK		0x00000100
26 #define SD0_ITAPDLYENA			0x00000100
27 #define SD1_ITAPDLYENA_MASK		0x01000000
28 #define SD1_ITAPDLYENA			0x01000000
29 #define SD0_ITAPDLYSEL_MASK		0x000000FF
30 #define SD1_ITAPDLYSEL_MASK		0x00FF0000
31 #define SD0_OTAPDLYSEL_MASK		0x0000003F
32 #define SD1_OTAPDLYSEL_MASK		0x003F0000
33 
zynqmp_dll_reset(u8 deviceid)34 void zynqmp_dll_reset(u8 deviceid)
35 {
36 	/* Issue DLL Reset */
37 	if (deviceid == 0)
38 		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
39 				  SD0_DLL_RST);
40 	else
41 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
42 				  SD1_DLL_RST);
43 
44 	mdelay(1);
45 
46 	/* Release DLL Reset */
47 	if (deviceid == 0)
48 		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
49 	else
50 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
51 }
52 
arasan_zynqmp_set_tapdelay(u8 deviceid,u32 itap_delay,u32 otap_delay)53 void arasan_zynqmp_set_tapdelay(u8 deviceid, u32 itap_delay, u32 otap_delay)
54 {
55 	if (deviceid == 0) {
56 		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
57 				  SD0_DLL_RST);
58 		/* Program ITAP */
59 		if (itap_delay) {
60 			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
61 					  SD0_ITAPCHGWIN);
62 			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
63 					  SD0_ITAPDLYENA);
64 			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
65 					  itap_delay);
66 			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
67 					  0x0);
68 		}
69 
70 		/* Program OTAP */
71 		if (otap_delay)
72 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
73 					  otap_delay);
74 
75 		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
76 	} else {
77 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
78 				  SD1_DLL_RST);
79 		/* Program ITAP */
80 		if (itap_delay) {
81 			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
82 					  SD1_ITAPCHGWIN);
83 			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
84 					  SD1_ITAPDLYENA);
85 			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
86 					  (itap_delay << 16));
87 			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
88 					  0x0);
89 		}
90 
91 		/* Program OTAP */
92 		if (otap_delay)
93 			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
94 					  (otap_delay << 16));
95 
96 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
97 	}
98 }
99