|
@@ -0,0 +1,229 @@
|
|
|
+// 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);
|
|
|
+}
|