From 004eee86f1181f712345370163baa0d158716196 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Jun 2019 22:24:12 -0300 Subject: pico-imx6: Add initial support Add the initial support for the pico-imx6 variants. DDR initialization is based on the TechNexion's U-Boot code. Signed-off-by: Fabio Estevam Signed-off-by: Fabio Berton Signed-off-by: Otavio Salvador --- board/technexion/pico-imx6/Kconfig | 15 ++ board/technexion/pico-imx6/MAINTAINERS | 9 + board/technexion/pico-imx6/Makefile | 5 + board/technexion/pico-imx6/README | 73 ++++++++ board/technexion/pico-imx6/pico-imx6.c | 78 +++++++++ board/technexion/pico-imx6/spl.c | 303 +++++++++++++++++++++++++++++++++ 6 files changed, 483 insertions(+) create mode 100644 board/technexion/pico-imx6/Kconfig create mode 100644 board/technexion/pico-imx6/MAINTAINERS create mode 100644 board/technexion/pico-imx6/Makefile create mode 100644 board/technexion/pico-imx6/README create mode 100644 board/technexion/pico-imx6/pico-imx6.c create mode 100644 board/technexion/pico-imx6/spl.c (limited to 'board/technexion') diff --git a/board/technexion/pico-imx6/Kconfig b/board/technexion/pico-imx6/Kconfig new file mode 100644 index 0000000..4af18e5 --- /dev/null +++ b/board/technexion/pico-imx6/Kconfig @@ -0,0 +1,15 @@ +if TARGET_PICO_IMX6 + +config SYS_BOARD + default "pico-imx6" + +config SYS_VENDOR + default "technexion" + +config SYS_SOC + default "mx6" + +config SYS_CONFIG_NAME + default "pico-imx6" + +endif diff --git a/board/technexion/pico-imx6/MAINTAINERS b/board/technexion/pico-imx6/MAINTAINERS new file mode 100644 index 0000000..dd6fb96 --- /dev/null +++ b/board/technexion/pico-imx6/MAINTAINERS @@ -0,0 +1,9 @@ +TECHNEXION PICO-IMX6 BOARD +M: Fabio Estevam +S: Maintained +F: arch/arm/dts/imx6qdl-pico.dtsi +F: arch/arm/dts/imx6q-pico.dts +F: arch/arm/dts/imx6dl-pico.dts +F: board/technexion/pico-imx6/ +F: include/configs/pico-imx6.h +F: configs/pico-imx6_defconfig diff --git a/board/technexion/pico-imx6/Makefile b/board/technexion/pico-imx6/Makefile new file mode 100644 index 0000000..ddb1604 --- /dev/null +++ b/board/technexion/pico-imx6/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2013 Freescale Semiconductor, Inc. + +obj-y := pico-imx6.o spl.o diff --git a/board/technexion/pico-imx6/README b/board/technexion/pico-imx6/README new file mode 100644 index 0000000..f1e84bf --- /dev/null +++ b/board/technexion/pico-imx6/README @@ -0,0 +1,73 @@ +How to Update U-Boot on pico-imx6q/dl boards +-------------------------------------------- + +Required software on the host PC: + +- UUU: https://github.com/NXPmicro/mfgtools + +Build U-Boot for pico: + +$ make mrproper +$ make pico-imx6_defconfig +$ make + +This generates the SPL and u-boot-dtb.img binaries. + +1. Loading U-Boot via USB Serial Download Protocol + +Note: This method is convenient for development purposes. +If the eMMC has already a U-Boot flashed then the user can +go to step 2 below in order to update U-Boot. + +Put pico board in USB download mode (Refer to the following link for details: +https://www.technexion.com/support/knowledgebase/boot-configuration-settings-for-pico-baseboards/). + +Connect a USB to serial adapter between the host PC and pico. + +Connect a USB cable between the OTG pico port and the host PC. + +Open a terminal program such as minicom. + +Copy SPL and u-boot-dtb.img to the uuu folder. + +Load the U-Boot via USB: + +$ sudo ./uuu -v uuu_script + +where uuu_script contains the following: + +SDP: boot -f SPL +SDPU: write -f u-boot-dtb.img -addr 0x10000000 +SDPU: jump -addr 0x10000000 + +Then U-Boot starts and its messages appear in the console program. + +Use the default environment variables: + +=> env default -f -a +=> saveenv + +2. Flashing U-Boot into the eMMC + +The default U-Boot environment expects the use of eMMC user +partition. To ensure we are using the proper eMMC partition for boot, +please run: + +=> mmc partconf 0 0 0 0 + +Next, run the DFU agent so we can flash the new images using dfu-util +tool: + +=> dfu 0 mmc 0 + +Flash SPL and u-boot-dtb.img into the eMMC running the following commands on a PC: + +$ sudo dfu-util -D SPL -a spl + +$ sudo dfu-util -D u-boot-dtb.img -a u-boot + +Remove power from the pico board. + +Put pico board into normal boot mode. + +Power up the board and the new updated U-Boot should boot from eMMC. diff --git a/board/technexion/pico-imx6/pico-imx6.c b/board/technexion/pico-imx6/pico-imx6.c new file mode 100644 index 0000000..717f20d --- /dev/null +++ b/board/technexion/pico-imx6/pico-imx6.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * Copyright (C) 2014 O.S. Systems Software LTDA. + * + * Author: Fabio Estevam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ + PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +int dram_init(void) +{ + gd->ram_size = imx_ddr_size(); + + return 0; +} + +static iomux_v3_cfg_t const uart1_pads[] = { + IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), + IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), +}; + +static void setup_iomux_uart(void) +{ + SETUP_IOMUX_PADS(uart1_pads); +} + +int board_early_init_f(void) +{ + setup_iomux_uart(); + + return 0; +} + +int overwrite_console(void) +{ + return 1; +} + +int board_late_init(void) +{ + if (is_mx6dq()) + env_set("board_rev", "MX6Q"); + else + env_set("board_rev", "MX6DL"); + + return 0; +} + +int board_init(void) +{ + gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; + + return 0; +} + +int checkboard(void) +{ + puts("Board: PICO-IMX6\n"); + + return 0; +} diff --git a/board/technexion/pico-imx6/spl.c b/board/technexion/pico-imx6/spl.c new file mode 100644 index 0000000..5bf8702 --- /dev/null +++ b/board/technexion/pico-imx6/spl.c @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Technexion Ltd. + * + * Author: Richard Hu + * Fabio Estevam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_SPL_BUILD) +#include + +#define IMX6DQ_DRIVE_STRENGTH 0x30 +#define IMX6SDL_DRIVE_STRENGTH 0x28 + +/* configure MX6Q/DUAL mmdc DDR io registers */ +static struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = { + .dram_sdclk_0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdclk_1 = IMX6DQ_DRIVE_STRENGTH, + .dram_cas = IMX6DQ_DRIVE_STRENGTH, + .dram_ras = IMX6DQ_DRIVE_STRENGTH, + .dram_reset = IMX6DQ_DRIVE_STRENGTH, + .dram_sdcke0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdcke1 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdba2 = 0x00000000, + .dram_sdodt0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdodt1 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs1 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs2 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs3 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs4 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs5 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs6 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs7 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm0 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm1 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm2 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm3 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm4 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm5 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm6 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm7 = IMX6DQ_DRIVE_STRENGTH, +}; + +/* configure MX6Q/DUAL mmdc GRP io registers */ +static struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = { + .grp_ddr_type = 0x000c0000, + .grp_ddrmode_ctl = 0x00020000, + .grp_ddrpke = 0x00000000, + .grp_addds = IMX6DQ_DRIVE_STRENGTH, + .grp_ctlds = IMX6DQ_DRIVE_STRENGTH, + .grp_ddrmode = 0x00020000, + .grp_b0ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b1ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b2ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b3ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b4ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b5ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b6ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b7ds = IMX6DQ_DRIVE_STRENGTH, +}; + +/* configure MX6SOLO/DUALLITE mmdc DDR io registers */ +struct mx6sdl_iomux_ddr_regs mx6sdl_ddr_ioregs = { + .dram_sdclk_0 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdclk_1 = IMX6SDL_DRIVE_STRENGTH, + .dram_cas = IMX6SDL_DRIVE_STRENGTH, + .dram_ras = IMX6SDL_DRIVE_STRENGTH, + .dram_reset = IMX6SDL_DRIVE_STRENGTH, + .dram_sdcke0 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdcke1 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdba2 = 0x00000000, + .dram_sdodt0 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdodt1 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdqs0 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdqs1 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdqs2 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdqs3 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdqs4 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdqs5 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdqs6 = IMX6SDL_DRIVE_STRENGTH, + .dram_sdqs7 = IMX6SDL_DRIVE_STRENGTH, + .dram_dqm0 = IMX6SDL_DRIVE_STRENGTH, + .dram_dqm1 = IMX6SDL_DRIVE_STRENGTH, + .dram_dqm2 = IMX6SDL_DRIVE_STRENGTH, + .dram_dqm3 = IMX6SDL_DRIVE_STRENGTH, + .dram_dqm4 = IMX6SDL_DRIVE_STRENGTH, + .dram_dqm5 = IMX6SDL_DRIVE_STRENGTH, + .dram_dqm6 = IMX6SDL_DRIVE_STRENGTH, + .dram_dqm7 = IMX6SDL_DRIVE_STRENGTH, +}; + +/* configure MX6SOLO/DUALLITE mmdc GRP io registers */ +struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = { + .grp_ddr_type = 0x000c0000, + .grp_ddrmode_ctl = 0x00020000, + .grp_ddrpke = 0x00000000, + .grp_addds = IMX6SDL_DRIVE_STRENGTH, + .grp_ctlds = IMX6SDL_DRIVE_STRENGTH, + .grp_ddrmode = 0x00020000, + .grp_b0ds = IMX6SDL_DRIVE_STRENGTH, + .grp_b1ds = IMX6SDL_DRIVE_STRENGTH, + .grp_b2ds = IMX6SDL_DRIVE_STRENGTH, + .grp_b3ds = IMX6SDL_DRIVE_STRENGTH, + .grp_b4ds = IMX6SDL_DRIVE_STRENGTH, + .grp_b5ds = IMX6SDL_DRIVE_STRENGTH, + .grp_b6ds = IMX6SDL_DRIVE_STRENGTH, + .grp_b7ds = IMX6SDL_DRIVE_STRENGTH, +}; + +/* H5T04G63AFR-PB for i.mx6Solo/DL operating DDR at 400MHz */ +static struct mx6_ddr3_cfg h5t04g63afr = { + .mem_speed = 800, + .density = 4, + .width = 16, + .banks = 8, + .rowaddr = 15, + .coladdr = 10, + .pagesz = 2, + .trcd = 1500, + .trcmin = 5250, + .trasmin = 3750, +}; + +/* H5TQ2G63FFR-H9 for i.mx6Solo/DL operating DDR at 400MHz */ +static struct mx6_ddr3_cfg h5tq2g63ffr = { + .mem_speed = 800, + .density = 2, + .width = 16, + .banks = 8, + .rowaddr = 14, + .coladdr = 10, + .pagesz = 2, + .trcd = 1500, + .trcmin = 5250, + .trasmin = 3750, +}; + +static struct mx6_mmdc_calibration mx6q_1g_mmdc_calib = { + .p0_mpwldectrl0 = 0x00000000, + .p0_mpwldectrl1 = 0x00000000, + .p1_mpwldectrl0 = 0x00000000, + .p1_mpwldectrl1 = 0x00000000, + .p0_mpdgctrl0 = 0x032C0340, + .p0_mpdgctrl1 = 0x03300324, + .p1_mpdgctrl0 = 0x032C0338, + .p1_mpdgctrl1 = 0x03300274, + .p0_mprddlctl = 0x423A383E, + .p1_mprddlctl = 0x3638323E, + .p0_mpwrdlctl = 0x363C4640, + .p1_mpwrdlctl = 0x4034423C, +}; + +/* DDR 32bit */ +static struct mx6_ddr_sysinfo mem_s = { + .dsize = 1, + .cs1_mirror = 0, + /* config for full 4GB range so that get_mem_size() works */ + .cs_density = 32, + .ncs = 1, + .bi_on = 1, + .rtt_nom = 1, + .rtt_wr = 0, + .ralat = 5, + .walat = 0, + .mif3_mode = 3, + .rst_to_cke = 0x23, + .sde_to_rst = 0x10, +}; + +static struct mx6_mmdc_calibration mx6dl_1g_mmdc_calib = { + .p0_mpwldectrl0 = 0x001f001f, + .p0_mpwldectrl1 = 0x001f001f, + .p1_mpwldectrl0 = 0x001f001f, + .p1_mpwldectrl1 = 0x001f001f, + .p0_mpdgctrl0 = 0x420e020e, + .p0_mpdgctrl1 = 0x02000200, + .p1_mpdgctrl0 = 0x42020202, + .p1_mpdgctrl1 = 0x01720172, + .p0_mprddlctl = 0x494c4f4c, + .p1_mprddlctl = 0x4a4c4c49, + .p0_mpwrdlctl = 0x3f3f3133, + .p1_mpwrdlctl = 0x39373f2e, +}; + +static struct mx6_mmdc_calibration mx6s_512m_mmdc_calib = { + .p0_mpwldectrl0 = 0x0040003c, + .p0_mpwldectrl1 = 0x0032003e, + .p0_mpdgctrl0 = 0x42350231, + .p0_mpdgctrl1 = 0x021a0218, + .p0_mprddlctl = 0x4b4b4e49, + .p0_mpwrdlctl = 0x3f3f3035, +}; + +static void ccgr_init(void) +{ + struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + writel(0x00C03F3F, &ccm->CCGR0); + writel(0x0030FC03, &ccm->CCGR1); + writel(0x0FFFC000, &ccm->CCGR2); + writel(0x3FF03000, &ccm->CCGR3); + writel(0x00FFF300, &ccm->CCGR4); + writel(0x0F0000C3, &ccm->CCGR5); + writel(0x000003FF, &ccm->CCGR6); +} + +static void spl_dram_init(void) +{ + if (is_mx6solo()) { + mx6sdl_dram_iocfg(32, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs); + mx6_dram_cfg(&mem_s, &mx6s_512m_mmdc_calib, &h5tq2g63ffr); + } else if (is_mx6dl()) { + mx6sdl_dram_iocfg(32, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs); + mx6_dram_cfg(&mem_s, &mx6dl_1g_mmdc_calib, &h5t04g63afr); + } else if (is_mx6dq()) { + mx6dq_dram_iocfg(32, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs); + mx6_dram_cfg(&mem_s, &mx6q_1g_mmdc_calib, &h5t04g63afr); + } + + udelay(100); +} + +void board_init_f(ulong dummy) +{ + ccgr_init(); + + /* setup AIPS and disable watchdog */ + arch_cpu_init(); + + gpr_init(); + + /* iomux */ + board_early_init_f(); + + /* setup GP timer */ + timer_init(); + + /* UART clocks enabled and gd valid - init serial console */ + preloader_console_init(); + + /* DDR initialization */ + spl_dram_init(); +} + +#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \ + PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ + PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +static struct fsl_esdhc_cfg usdhc_cfg[1] = { + {USDHC3_BASE_ADDR}, +}; + +static iomux_v3_cfg_t const usdhc3_pads[] = { + IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + /* SOM MicroSD Card Detect */ + IOMUX_PADS(PAD_EIM_DA9__GPIO3_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL)), +}; + +int board_mmc_getcd(struct mmc *mmc) +{ + return 1; +} + +int board_mmc_init(bd_t *bis) +{ + SETUP_IOMUX_PADS(usdhc3_pads); + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); + return fsl_esdhc_initialize(bis, &usdhc_cfg[0]); +} +#endif + +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ + if (is_mx6dq() && !strcmp(name, "imx6q-pico")) + return 0; + else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-pico")) + return 0; + + return -EINVAL; +} +#endif -- cgit v1.1