From 0266042714b2e0a17e397fe5d8a29a4487785df4 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 14 Feb 2020 11:53:38 +0100 Subject: ARM: i.MX8M: Add DDR controller support This adds the DDR driver for the i.MX8MQ/i.MX8MM. It's taken from U-Boot v2020.04-rc1 with slight modifications for barebox The i.MX8MQ boards in the tree currently use the output of an earlier version of the NXP i.MX8M DDR Tool which doesn't use a controller driver but instead does most stuff in board code. It seems this can coexist with the new driver, only a few helper functions that previously lived in arch/arm/mach-imx/imx8-ddrc.c are now provided by the new driver. Tested on an i.MX8MM EVK Signed-off-by: Sascha Hauer --- arch/arm/boards/nxp-imx8mq-evk/ddr.h | 9 +-- arch/arm/boards/nxp-imx8mq-evk/lowlevel.c | 2 +- arch/arm/boards/phytec-som-imx8mq/ddr.h | 7 +- arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c | 1 - arch/arm/boards/phytec-som-imx8mq/lowlevel.c | 2 +- arch/arm/boards/zii-imx8mq-dev/ddr.h | 9 +-- arch/arm/boards/zii-imx8mq-dev/lowlevel.c | 2 +- arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/Makefile | 2 +- arch/arm/mach-imx/imx8-ddrc.c | 91 ------------------------ arch/arm/mach-imx/include/mach/imx8-ddrc.h | 66 ----------------- 11 files changed, 8 insertions(+), 184 deletions(-) delete mode 100644 arch/arm/mach-imx/imx8-ddrc.c delete mode 100644 arch/arm/mach-imx/include/mach/imx8-ddrc.h (limited to 'arch') diff --git a/arch/arm/boards/nxp-imx8mq-evk/ddr.h b/arch/arm/boards/nxp-imx8mq-evk/ddr.h index 65115dba1e..fd09ad6bf1 100644 --- a/arch/arm/boards/nxp-imx8mq-evk/ddr.h +++ b/arch/arm/boards/nxp-imx8mq-evk/ddr.h @@ -8,7 +8,7 @@ */ #include #include -#include +#include /* * Code generated by i.MX8 M DDR Tool doesn't have any prefixes in the @@ -20,10 +20,3 @@ void nxp_imx8mq_evk_ddr_init(void); void nxp_imx8mq_evk_ddr_cfg_phy(void); - -#define FW_1D_IMAGE lpddr4_pmu_train_1d_imem_bin, \ - lpddr4_pmu_train_1d_dmem_bin -#define FW_2D_IMAGE lpddr4_pmu_train_2d_imem_bin, \ - lpddr4_pmu_train_2d_dmem_bin - - diff --git a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c index bf3d43b9a3..39358afad1 100644 --- a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/boards/phytec-som-imx8mq/ddr.h b/arch/arm/boards/phytec-som-imx8mq/ddr.h index 18ae6e9022..e125feaaf0 100644 --- a/arch/arm/boards/phytec-som-imx8mq/ddr.h +++ b/arch/arm/boards/phytec-som-imx8mq/ddr.h @@ -7,7 +7,7 @@ */ #include #include -#include +#include /* * Code generated by i.MX8 M DDR Tool doesn't have any prefixes in the @@ -19,8 +19,3 @@ void phytec_imx8mq_phycore_ddr_init(void); void phytec_imx8mq_phycore_ddr_cfg_phy(void); - -#define FW_1D_IMAGE lpddr4_pmu_train_1d_imem_bin, \ - lpddr4_pmu_train_1d_dmem_bin -#define FW_2D_IMAGE lpddr4_pmu_train_2d_imem_bin, \ - lpddr4_pmu_train_2d_dmem_bin diff --git a/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c b/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c index 56af647821..cc00527649 100644 --- a/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c +++ b/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c @@ -9,7 +9,6 @@ #include "ddr.h" -extern void wait_ddrphy_training_complete(void); void ddr_cfg_phy(void) { unsigned int tmp, tmp_t; diff --git a/arch/arm/boards/phytec-som-imx8mq/lowlevel.c b/arch/arm/boards/phytec-som-imx8mq/lowlevel.c index f460901a2c..f5b9b6c008 100644 --- a/arch/arm/boards/phytec-som-imx8mq/lowlevel.c +++ b/arch/arm/boards/phytec-som-imx8mq/lowlevel.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/boards/zii-imx8mq-dev/ddr.h b/arch/arm/boards/zii-imx8mq-dev/ddr.h index 1293ad3f34..a395211e62 100644 --- a/arch/arm/boards/zii-imx8mq-dev/ddr.h +++ b/arch/arm/boards/zii-imx8mq-dev/ddr.h @@ -8,7 +8,7 @@ */ #include #include -#include +#include /* * Code generated by i.MX8 M DDR Tool doesn't have any prefixes in the @@ -20,10 +20,3 @@ void zii_imx8mq_rdu3_ddr_init(void); void zii_imx8mq_rdu3_ddr_cfg_phy(void); - -#define FW_1D_IMAGE lpddr4_pmu_train_1d_imem_bin, \ - lpddr4_pmu_train_1d_dmem_bin -#define FW_2D_IMAGE lpddr4_pmu_train_2d_imem_bin, \ - lpddr4_pmu_train_2d_dmem_bin - - diff --git a/arch/arm/boards/zii-imx8mq-dev/lowlevel.c b/arch/arm/boards/zii-imx8mq-dev/lowlevel.c index 2646f5fc3e..6400833809 100644 --- a/arch/arm/boards/zii-imx8mq-dev/lowlevel.c +++ b/arch/arm/boards/zii-imx8mq-dev/lowlevel.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index d717d83865..7b79d80748 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -183,6 +183,7 @@ config ARCH_IMX8M select COMMON_CLK_OF_PROVIDER select ARCH_HAS_FEC_IMX select HW_HAS_PCI + select IMX8M_DRAM select PBL_VERIFY_PIGGY if HABV4 config ARCH_IMX8MQ diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 862dc78ff2..105785ba1b 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -16,7 +16,7 @@ lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o obj-$(CONFIG_ARCH_IMX7) += imx7.o obj-$(CONFIG_ARCH_VF610) += vf610.o obj-$(CONFIG_ARCH_IMX8M) += imx8m.o -lwl-$(CONFIG_ARCH_IMX8MQ) += imx8-ddrc.o atf.o +lwl-$(CONFIG_ARCH_IMX8MQ) += atf.o obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_NAND_IMX) += nand.o lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o diff --git a/arch/arm/mach-imx/imx8-ddrc.c b/arch/arm/mach-imx/imx8-ddrc.c deleted file mode 100644 index 8bb2672102..0000000000 --- a/arch/arm/mach-imx/imx8-ddrc.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include - -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 - * Wait for it indefinitely. - */ - 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; - - for (i = 0; i < index; i++) - ddrc_phy_get_message(phy, PMC_MESSAGE_STREAM); -} - -void ddrc_phy_wait_training_complete(void __iomem *phy) -{ - for (;;) { - const u32 m = ddrc_phy_get_message(phy, PMC_MESSAGE_ID); - - switch (m) { - case PMC_TRAIN_STREAM_START: - ddrc_phy_fetch_streaming_message(phy); - break; - case PMC_TRAIN_SUCCESS: - return; - case PMC_TRAIN_FAIL: - hang(); - } - } -} diff --git a/arch/arm/mach-imx/include/mach/imx8-ddrc.h b/arch/arm/mach-imx/include/mach/imx8-ddrc.h deleted file mode 100644 index d49e29f263..0000000000 --- a/arch/arm/mach-imx/include/mach/imx8-ddrc.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __IMX8_DDRC_H__ -#define __IMX8_DDRC_H__ - -#include -#include -#include -#include - -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 -- cgit v1.2.3