mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Andrey Smirnov <andrew.smirnov@gmail.com>
To: barebox@lists.infradead.org
Cc: Andrey Smirnov <andrew.smirnov@gmail.com>
Subject: [RESEND v3 37/52] ARM: i.MX8: Add DDRC PHY support code
Date: Thu,  7 Jun 2018 06:00:53 -0700	[thread overview]
Message-ID: <20180607130108.5339-38-andrew.smirnov@gmail.com> (raw)
In-Reply-To: <20180607130108.5339-1-andrew.smirnov@gmail.com>

Add DDRC PHY support code needed to upload DDR training firwmare as
well as to wait for the training process to complete.

Those are needed to support board specific DDR initialization code.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/Makefile                 |   1 +
 arch/arm/mach-imx/imx8-ddrc.c              | 114 +++++++++++++++++++++
 arch/arm/mach-imx/include/mach/imx8-ddrc.h |  66 ++++++++++++
 3 files changed, 181 insertions(+)
 create mode 100644 arch/arm/mach-imx/imx8-ddrc.c
 create mode 100644 arch/arm/mach-imx/include/mach/imx8-ddrc.h

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 442039a27..28fe60dba 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -17,6 +17,7 @@ lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
 obj-$(CONFIG_ARCH_IMX7) += imx7.o
 obj-$(CONFIG_ARCH_VF610) += vf610.o
 obj-$(CONFIG_ARCH_IMX8MQ) += imx8mq.o
+lwl-$(CONFIG_ARCH_IMX8MQ) += imx8-ddrc.o
 obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o
 obj-$(CONFIG_IMX_IIM)	+= iim.o
 obj-$(CONFIG_NAND_IMX) += nand.o
diff --git a/arch/arm/mach-imx/imx8-ddrc.c b/arch/arm/mach-imx/imx8-ddrc.c
new file mode 100644
index 000000000..5a9a78876
--- /dev/null
+++ b/arch/arm/mach-imx/imx8-ddrc.c
@@ -0,0 +1,114 @@
+/*
+ * Define dummy get_time_ns() in order to be able to use
+ * readl_poll_timeout(). This has to happen before inclusion of
+ * <clock.h> which will happen in <common.h>
+ */
+#define get_time_ns()	0
+
+#include <common.h>
+#include <linux/iopoll.h>
+#include <mach/imx8-ddrc.h>
+#include <debug_ll.h>
+
+void ddrc_phy_load_firmware(void __iomem *phy,
+			    enum ddrc_phy_firmware_offset offset,
+			    const u16 *blob, size_t size)
+{
+	while (size) {
+		writew(*blob++, phy + DDRC_PHY_REG(offset));
+		offset++;
+		size -= sizeof(*blob);
+	}
+}
+
+enum pmc_constants {
+	PMC_MESSAGE_ID,
+	PMC_MESSAGE_STREAM,
+
+	PMC_TRAIN_SUCCESS	= 0x07,
+	PMC_TRAIN_STREAM_START	= 0x08,
+	PMC_TRAIN_FAIL		= 0xff,
+};
+
+static u32 ddrc_phy_get_message(void __iomem *phy, int type)
+{
+	u32 r, message;
+
+	/*
+	 * When BIT0 set to 0, the PMU has a message for the user
+	 * 10ms seems not enough for poll message, so use 1s here.
+	 */
+	readl_poll_timeout(phy + DDRC_PHY_REG(0xd0004),
+			   r, !(r & BIT(0)), 0);
+
+	switch (type) {
+	case PMC_MESSAGE_ID:
+		/*
+		 * Get the major message ID
+		 */
+		message = readl(phy + DDRC_PHY_REG(0xd0032));
+		break;
+	case PMC_MESSAGE_STREAM:
+		message = readl(phy + DDRC_PHY_REG(0xd0034));
+		message <<= 16;
+		message |= readl(phy + DDRC_PHY_REG(0xd0032));
+		break;
+	}
+
+	/*
+	 * By setting this register to 0, the user acknowledges the
+	 * receipt of the message.
+	 */
+	writel(0x00000000, phy + DDRC_PHY_REG(0xd0031));
+	/*
+	 * When BIT0 set to 0, the PMU has a message for the user
+	 */
+	readl_poll_timeout(phy + DDRC_PHY_REG(0xd0004),
+			   r, r & BIT(0), 0);
+
+	writel(0x00000001, phy + DDRC_PHY_REG(0xd0031));
+
+	return message;
+}
+
+static void ddrc_phy_fetch_streaming_message(void __iomem *phy)
+{
+	const u16 index = ddrc_phy_get_message(phy, PMC_MESSAGE_STREAM);
+	u16 i;
+
+	putc_ll('|');
+	puthex_ll(index);
+
+	for (i = 0; i < index; i++) {
+		const u32 arg = ddrc_phy_get_message(phy, PMC_MESSAGE_STREAM);
+
+		putc_ll('|');
+		puthex_ll(arg);
+	}
+}
+
+void ddrc_phy_wait_training_complete(void __iomem *phy)
+{
+	for (;;) {
+		const u32 m = ddrc_phy_get_message(phy, PMC_MESSAGE_ID);
+
+		puthex_ll(m);
+
+		switch (m) {
+		case PMC_TRAIN_STREAM_START:
+			ddrc_phy_fetch_streaming_message(phy);
+			break;
+		case PMC_TRAIN_SUCCESS:
+			putc_ll('P');
+			putc_ll('\r');
+			putc_ll('\n');
+			return;
+		case PMC_TRAIN_FAIL:
+			putc_ll('F');
+			hang();
+		}
+
+		putc_ll('\r');
+		putc_ll('\n');
+	}
+}
\ No newline at end of file
diff --git a/arch/arm/mach-imx/include/mach/imx8-ddrc.h b/arch/arm/mach-imx/include/mach/imx8-ddrc.h
new file mode 100644
index 000000000..d49e29f26
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/imx8-ddrc.h
@@ -0,0 +1,66 @@
+#ifndef __IMX8_DDRC_H__
+#define __IMX8_DDRC_H__
+
+#include <mach/imx8mq-regs.h>
+#include <io.h>
+#include <firmware.h>
+#include <linux/compiler.h>
+
+enum ddrc_phy_firmware_offset {
+	DDRC_PHY_IMEM = 0x00050000U,
+	DDRC_PHY_DMEM = 0x00054000U,
+};
+
+void ddrc_phy_load_firmware(void __iomem *,
+			    enum ddrc_phy_firmware_offset,
+			    const u16 *, size_t);
+
+#define DDRC_PHY_REG(x)	((x) * 4)
+
+void ddrc_phy_wait_training_complete(void __iomem *phy);
+
+
+/*
+ * i.MX8M DDR Tool compatibility layer
+ */
+
+#define reg32_write(a, v)	writel(v, a)
+#define reg32_read(a)		readl(a)
+
+static inline void wait_ddrphy_training_complete(void)
+{
+	ddrc_phy_wait_training_complete(IOMEM(MX8MQ_DDRC_PHY_BASE_ADDR));
+}
+
+#define __ddr_load_train_code(imem, dmem)				\
+	do {								\
+		const u16 *__mem;					\
+		size_t __size;						\
+									\
+		get_builtin_firmware(imem, &__mem, &__size);		\
+		ddrc_phy_load_firmware(IOMEM(MX8MQ_DDRC_PHY_BASE_ADDR),	\
+				       DDRC_PHY_IMEM, __mem, __size);	\
+									\
+		get_builtin_firmware(dmem, &__mem, &__size);		\
+		ddrc_phy_load_firmware(IOMEM(MX8MQ_DDRC_PHY_BASE_ADDR),	\
+				       DDRC_PHY_DMEM, __mem, __size);	\
+	} while (0)
+
+#define ddr_load_train_code(imem_dmem) __ddr_load_train_code(imem_dmem)
+
+#define DDRC_IPS_BASE_ADDR(X) (0x3d400000 + (X * 0x2000000))
+
+#define DDRC_STAT(X)             (DDRC_IPS_BASE_ADDR(X) + 0x04)
+#define DDRC_MRSTAT(X)           (DDRC_IPS_BASE_ADDR(X) + 0x18)
+#define DDRC_PWRCTL(X)           (DDRC_IPS_BASE_ADDR(X) + 0x30)
+#define DDRC_RFSHCTL3(X)         (DDRC_IPS_BASE_ADDR(X) + 0x60)
+#define DDRC_CRCPARSTAT(X)       (DDRC_IPS_BASE_ADDR(X) + 0xcc)
+#define DDRC_DFIMISC(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1b0)
+#define DDRC_DFISTAT(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1bc)
+#define DDRC_SWCTL(X)            (DDRC_IPS_BASE_ADDR(X) + 0x320)
+#define DDRC_SWSTAT(X)           (DDRC_IPS_BASE_ADDR(X) + 0x324)
+#define DDRC_PCTRL_0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x490)
+
+#define IP2APB_DDRPHY_IPS_BASE_ADDR(X) (0x3c000000 + (X * 0x2000000))
+
+#endif
\ No newline at end of file
-- 
2.17.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2018-06-07 13:03 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-07 13:00 [RESEND v3 00/52] ARM: i.MX8MQ and EVK support Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 01/52] ARM: i.MX: xload: Fix compiler warning Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 02/52] ARM: i.MX: compile arm32 specific errata only for CPU32 Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 03/52] ARM: Add i.MX8 support Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 04/52] aarch64: Add i.MX8 debug UART support Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 05/52] Include our own include/dt-bindings Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 06/52] mci: imx-esdhc: use dma mapping functions Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 07/52] net: fec_imx: remove unnecessary DMA sync ops Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 08/52] net: fec_imx: Use dma mapping functions Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 09/52] net: fec_imx: Make use of IS_ALIGNED Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 10/52] clock: Add i.MX8MQ clock driver Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 11/52] serial: i.MX: Add i.MX8 support Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 12/52] mmc: i.MX esdhc: " Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 13/52] gpio: i.MX: Add i.MX8mq support Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 14/52] ARM: i.MX: ocotp: Add i.MX8MQ support Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 15/52] ARM: i.MX: Split shared CCM code into a separate file Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 16/52] ARM: i.MX: Add IOMUX pad constants for i.MX8 Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 17/52] ARM: i.MX: Add basic CCM " Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 18/52] ARM: Add constants and helpers for system counter interface Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 19/52] clocksource: armv8-timer: Convert explicit assembly into helpers Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 20/52] ARM: i.MX8: Initialize system counter Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 21/52] ARM: i.MX: boot: Fix address casting on 64-bit platforms Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 22/52] ARM: boot: Add trivial i.MX8 support Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 23/52] ARM: i.MX: xload-esdhc: Rework to make code be less i.MX6-specific Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 24/52] ARM: i.MX: xload-esdhc: Allow custom buffer address, device offset Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 25/52] ARM: i.MX: xload-esdhc: Add support for i.MX8 Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 26/52] pinctrl: i.MX: " Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 27/52] Documentation: imx: Change block size for 'dd' to 1024 Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 28/52] Documentation: i.MX: Add missing <soctype> Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 29/52] clocksource: armv8-timer: Make armv8_clocksource_read() static Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 30/52] clocksource: armv8-timer: Make use of postcore_platform_driver() Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 31/52] Port <linux/iopoll.h> from U-Boot Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 32/52] common/clock: Move delay and timeout functions to clock.h Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 33/52] clock: Use udelay() to implement mdelay() Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 34/52] ARM: i.MX8: Add DDRC PHY and DDR CTL base addresses Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 35/52] Kbuild: Add $(quote) Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 36/52] Add builtin firmware support Andrey Smirnov
2018-06-07 13:00 ` Andrey Smirnov [this message]
2018-06-07 13:00 ` [RESEND v3 38/52] ARM: Specify HAVE_PBL_IMAGE for CPU_64 Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 39/52] ARM: lib64: Make string functions aware of MMU configuration Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 40/52] ARM: mmu: Make use of dsb() and isb() helpers Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 41/52] ARM: cache: Remove unused cache ops struct Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 42/52] ARM: no-mmu: Disable building for ARMv8 Andrey Smirnov
2018-06-07 13:00 ` [RESEND v3 43/52] ARM: interrupts64: Include ESR value in exception traceback Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 44/52] ARM: mmu64: Trivial code simplification Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 45/52] ARM: mmu64: Make use of create_table() Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 46/52] ARM: mmu64: Convert flags in arch_remap_range() Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 47/52] ARM: include: dma: Add missing no-MMU stubs Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 48/52] scripts: imx-image: Drop error return from write_dcd() Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 49/52] scripts: imx-image: Limit v2 header size to HEADER_LEN Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 50/52] scripts: imx-image: Share the code to write barebox header Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 51/52] scripts: imx-image: Add i.MX8MQ support Andrey Smirnov
2018-06-07 13:01 ` [RESEND v3 52/52] ARM: i.MX8: Add i.MX8mq EVK support Andrey Smirnov
2018-06-08  6:46 ` [RESEND v3 00/52] ARM: i.MX8MQ and " Sascha Hauer
2018-06-11 17:56   ` Andrey Smirnov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180607130108.5339-38-andrew.smirnov@gmail.com \
    --to=andrew.smirnov@gmail.com \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox