uboot/board/liebherr/display5/spl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2017 DENX Software Engineering
   4 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
   5 */
   6
   7#include <common.h>
   8#include <cpu_func.h>
   9#include <env.h>
  10#include <image.h>
  11#include <init.h>
  12#include <log.h>
  13#include <serial.h>
  14#include <spl.h>
  15#include <asm/global_data.h>
  16#include <linux/delay.h>
  17#include <linux/libfdt.h>
  18#include <asm/io.h>
  19#include <asm/arch/clock.h>
  20#include <asm/arch/mx6-ddr.h>
  21#include <asm/arch/mx6-pins.h>
  22#include "asm/arch/crm_regs.h"
  23#include <asm/arch/sys_proto.h>
  24#include <asm/arch/imx-regs.h>
  25#include "asm/arch/iomux.h"
  26#include <asm/mach-imx/iomux-v3.h>
  27#include <asm/gpio.h>
  28#include <fsl_esdhc_imx.h>
  29#include <netdev.h>
  30#include <bootcount.h>
  31#include <watchdog.h>
  32#include "common.h"
  33
  34DECLARE_GLOBAL_DATA_PTR;
  35
  36static const struct mx6dq_iomux_ddr_regs mx6_ddr_ioregs = {
  37        .dram_sdclk_0 = 0x00000030,
  38        .dram_sdclk_1 = 0x00000030,
  39        .dram_cas = 0x00000030,
  40        .dram_ras = 0x00000030,
  41        .dram_reset = 0x00000030,
  42        .dram_sdcke0 = 0x00003000,
  43        .dram_sdcke1 = 0x00003000,
  44        .dram_sdba2 = 0x00000000,
  45        .dram_sdodt0 = 0x00000030,
  46        .dram_sdodt1 = 0x00000030,
  47
  48        .dram_sdqs0 = 0x00000030,
  49        .dram_sdqs1 = 0x00000030,
  50        .dram_sdqs2 = 0x00000030,
  51        .dram_sdqs3 = 0x00000030,
  52        .dram_sdqs4 = 0x00000030,
  53        .dram_sdqs5 = 0x00000030,
  54        .dram_sdqs6 = 0x00000030,
  55        .dram_sdqs7 = 0x00000030,
  56
  57        .dram_dqm0 = 0x00000030,
  58        .dram_dqm1 = 0x00000030,
  59        .dram_dqm2 = 0x00000030,
  60        .dram_dqm3 = 0x00000030,
  61        .dram_dqm4 = 0x00000030,
  62        .dram_dqm5 = 0x00000030,
  63        .dram_dqm6 = 0x00000030,
  64        .dram_dqm7 = 0x00000030,
  65};
  66
  67static const struct mx6dq_iomux_grp_regs mx6_grp_ioregs = {
  68        .grp_ddr_type = 0x000c0000,
  69        .grp_ddrmode_ctl = 0x00020000,
  70        .grp_ddrpke = 0x00000000,
  71        .grp_addds = 0x00000030,
  72        .grp_ctlds = 0x00000030,
  73        .grp_ddrmode = 0x00020000,
  74        .grp_b0ds = 0x00000030,
  75        .grp_b1ds = 0x00000030,
  76        .grp_b2ds = 0x00000030,
  77        .grp_b3ds = 0x00000030,
  78        .grp_b4ds = 0x00000030,
  79        .grp_b5ds = 0x00000030,
  80        .grp_b6ds = 0x00000030,
  81        .grp_b7ds = 0x00000030,
  82};
  83
  84/* 4x128Mx16.cfg */
  85static const struct mx6_mmdc_calibration mx6_4x256mx16_mmdc_calib = {
  86        .p0_mpwldectrl0 = 0x002D0028,
  87        .p0_mpwldectrl1 = 0x0032002D,
  88        .p1_mpwldectrl0 = 0x00210036,
  89        .p1_mpwldectrl1 = 0x0019002E,
  90        .p0_mpdgctrl0 = 0x4349035C,
  91        .p0_mpdgctrl1 = 0x0348033D,
  92        .p1_mpdgctrl0 = 0x43550362,
  93        .p1_mpdgctrl1 = 0x03520316,
  94        .p0_mprddlctl = 0x41393940,
  95        .p1_mprddlctl = 0x3F3A3C47,
  96        .p0_mpwrdlctl = 0x413A423A,
  97        .p1_mpwrdlctl = 0x4042483E,
  98};
  99
 100/* MT41K128M16JT-125 (2Gb density) */
 101static const struct mx6_ddr3_cfg mt41k128m16jt_125 = {
 102        .mem_speed = 1600,
 103        .density = 2,
 104        .width = 16,
 105        .banks = 8,
 106        .rowaddr = 14,
 107        .coladdr = 10,
 108        .pagesz = 2,
 109        .trcd = 1375,
 110        .trcmin = 4875,
 111        .trasmin = 3500,
 112};
 113
 114iomux_v3_cfg_t const uart_console_pads[] = {
 115        /* UART5 */
 116        MX6_PAD_CSI0_DAT14__UART5_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
 117        MX6_PAD_CSI0_DAT15__UART5_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
 118        MX6_PAD_CSI0_DAT18__UART5_RTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
 119        MX6_PAD_CSI0_DAT19__UART5_CTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
 120};
 121
 122void displ5_set_iomux_uart_spl(void)
 123{
 124        SETUP_IOMUX_PADS(uart_console_pads);
 125}
 126
 127iomux_v3_cfg_t const misc_pads_spl[] = {
 128        /* Emergency recovery pin */
 129        MX6_PAD_EIM_D29__GPIO3_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
 130};
 131
 132void displ5_set_iomux_misc_spl(void)
 133{
 134        SETUP_IOMUX_PADS(misc_pads_spl);
 135}
 136
 137#ifdef CONFIG_MXC_SPI
 138iomux_v3_cfg_t const ecspi2_pads[] = {
 139        /* SPI2, NOR Flash nWP, CS0 */
 140        MX6_PAD_CSI0_DAT10__ECSPI2_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
 141        MX6_PAD_CSI0_DAT9__ECSPI2_MOSI  | MUX_PAD_CTRL(SPI_PAD_CTRL),
 142        MX6_PAD_CSI0_DAT8__ECSPI2_SCLK  | MUX_PAD_CTRL(SPI_PAD_CTRL),
 143        MX6_PAD_CSI0_DAT11__GPIO5_IO29  | MUX_PAD_CTRL(NO_PAD_CTRL),
 144        MX6_PAD_SD3_DAT5__GPIO7_IO00    | MUX_PAD_CTRL(NO_PAD_CTRL),
 145};
 146
 147int board_spi_cs_gpio(unsigned int bus, unsigned int cs)
 148{
 149        if (bus != 1 || cs != 0)
 150                return -EINVAL;
 151
 152        return IMX_GPIO_NR(5, 29);
 153}
 154
 155void displ5_set_iomux_ecspi_spl(void)
 156{
 157        SETUP_IOMUX_PADS(ecspi2_pads);
 158}
 159
 160#else
 161void displ5_set_iomux_ecspi_spl(void) {}
 162#endif
 163
 164#ifdef CONFIG_FSL_ESDHC_IMX
 165iomux_v3_cfg_t const usdhc4_pads[] = {
 166        MX6_PAD_SD4_CLK__SD4_CLK        | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 167        MX6_PAD_SD4_CMD__SD4_CMD        | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 168        MX6_PAD_SD4_DAT0__SD4_DATA0     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 169        MX6_PAD_SD4_DAT1__SD4_DATA1     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 170        MX6_PAD_SD4_DAT2__SD4_DATA2     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 171        MX6_PAD_SD4_DAT3__SD4_DATA3     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 172        MX6_PAD_SD4_DAT4__SD4_DATA4     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 173        MX6_PAD_SD4_DAT5__SD4_DATA5     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 174        MX6_PAD_SD4_DAT6__SD4_DATA6     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 175        MX6_PAD_SD4_DAT7__SD4_DATA7     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 176        MX6_PAD_NANDF_ALE__SD4_RESET    | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 177};
 178
 179void displ5_set_iomux_usdhc_spl(void)
 180{
 181        SETUP_IOMUX_PADS(usdhc4_pads);
 182}
 183
 184#else
 185void displ5_set_iomux_usdhc_spl(void) {}
 186#endif
 187
 188static void ccgr_init(void)
 189{
 190        struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 191
 192        writel(0x00C03F3F, &ccm->CCGR0);
 193        writel(0x0030FC3F, &ccm->CCGR1);
 194        writel(0x0FFFCFC0, &ccm->CCGR2);
 195        writel(0x3FF00000, &ccm->CCGR3);
 196        writel(0x00FFF300, &ccm->CCGR4);
 197        writel(0x0F0000C3, &ccm->CCGR5);
 198        writel(0x000003FF, &ccm->CCGR6);
 199}
 200
 201#ifdef CONFIG_MX6_DDRCAL
 202static void spl_dram_print_cal(struct mx6_ddr_sysinfo const *sysinfo)
 203{
 204        struct mx6_mmdc_calibration calibration = {0};
 205
 206        mmdc_read_calibration(sysinfo, &calibration);
 207
 208        debug(".p0_mpdgctrl0\t= 0x%08X\n", calibration.p0_mpdgctrl0);
 209        debug(".p0_mpdgctrl1\t= 0x%08X\n", calibration.p0_mpdgctrl1);
 210        debug(".p0_mprddlctl\t= 0x%08X\n", calibration.p0_mprddlctl);
 211        debug(".p0_mpwrdlctl\t= 0x%08X\n", calibration.p0_mpwrdlctl);
 212        debug(".p0_mpwldectrl0\t= 0x%08X\n", calibration.p0_mpwldectrl0);
 213        debug(".p0_mpwldectrl1\t= 0x%08X\n", calibration.p0_mpwldectrl1);
 214        debug(".p1_mpdgctrl0\t= 0x%08X\n", calibration.p1_mpdgctrl0);
 215        debug(".p1_mpdgctrl1\t= 0x%08X\n", calibration.p1_mpdgctrl1);
 216        debug(".p1_mprddlctl\t= 0x%08X\n", calibration.p1_mprddlctl);
 217        debug(".p1_mpwrdlctl\t= 0x%08X\n", calibration.p1_mpwrdlctl);
 218        debug(".p1_mpwldectrl0\t= 0x%08X\n", calibration.p1_mpwldectrl0);
 219        debug(".p1_mpwldectrl1\t= 0x%08X\n", calibration.p1_mpwldectrl1);
 220}
 221
 222static void spl_dram_perform_cal(struct mx6_ddr_sysinfo const *sysinfo)
 223{
 224        int ret;
 225
 226        /* Perform DDR DRAM calibration */
 227        udelay(100);
 228        ret = mmdc_do_write_level_calibration(sysinfo);
 229        if (ret) {
 230                printf("DDR: Write level calibration error [%d]\n", ret);
 231                return;
 232        }
 233
 234        ret = mmdc_do_dqs_calibration(sysinfo);
 235        if (ret) {
 236                printf("DDR: DQS calibration error [%d]\n", ret);
 237                return;
 238        }
 239
 240        spl_dram_print_cal(sysinfo);
 241}
 242#endif /* CONFIG_MX6_DDRCAL */
 243
 244static void spl_dram_init(void)
 245{
 246        struct mx6_ddr_sysinfo sysinfo = {
 247                /* width of data bus:0=16,1=32,2=64 */
 248                .dsize = 2,
 249                /* config for full 4GB range so that get_mem_size() works */
 250                .cs_density = 32, /* 32Gb per CS */
 251                /* single chip select */
 252                .ncs = 1,
 253                .cs1_mirror = 0,
 254                .rtt_wr = 1 /*DDR3_RTT_60_OHM*/,        /* RTT_Wr = RZQ/4 */
 255                .rtt_nom = 2 /*DDR3_RTT_120_OHM*/,      /* RTT_Nom = RZQ/2 */
 256                .walat = 1,     /* Write additional latency */
 257                .ralat = 5,     /* Read additional latency */
 258                .mif3_mode = 3, /* Command prediction working mode */
 259                .bi_on = 1,     /* Bank interleaving enabled */
 260                .sde_to_rst = 0x10,     /* 14 cycles, 200us (JEDEC default) */
 261                .rst_to_cke = 0x23,     /* 33 cycles, 500us (JEDEC default) */
 262                .pd_fast_exit = 1, /* enable precharge power-down fast exit */
 263                .ddr_type = DDR_TYPE_DDR3,
 264                .refsel = 1,    /* Refresh cycles at 32KHz */
 265                .refr = 7,      /* 8 refresh commands per refresh cycle */
 266        };
 267
 268        mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs);
 269        mx6_dram_cfg(&sysinfo, &mx6_4x256mx16_mmdc_calib, &mt41k128m16jt_125);
 270
 271#ifdef CONFIG_MX6_DDRCAL
 272        spl_dram_perform_cal(&sysinfo);
 273#endif
 274}
 275
 276#ifdef CONFIG_SPL_SPI
 277static void displ5_init_ecspi(void)
 278{
 279        displ5_set_iomux_ecspi_spl();
 280        enable_spi_clk(1, 1);
 281}
 282#else
 283static inline void displ5_init_ecspi(void) { }
 284#endif
 285
 286#ifdef CONFIG_SPL_MMC
 287static struct fsl_esdhc_cfg usdhc_cfg = {
 288        .esdhc_base = USDHC4_BASE_ADDR,
 289        .max_bus_width = 8,
 290};
 291
 292int board_mmc_init(struct bd_info *bd)
 293{
 294        displ5_set_iomux_usdhc_spl();
 295
 296        usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
 297        gd->arch.sdhc_clk = usdhc_cfg.sdhc_clk;
 298
 299        return fsl_esdhc_initialize(bd, &usdhc_cfg);
 300}
 301#endif
 302
 303void board_init_f(ulong dummy)
 304{
 305        ccgr_init();
 306
 307        arch_cpu_init();
 308
 309        gpr_init();
 310
 311        /* setup GP timer */
 312        timer_init();
 313
 314        displ5_set_iomux_uart_spl();
 315
 316        /* UART clocks enabled and gd valid - init serial console */
 317        preloader_console_init();
 318
 319        displ5_init_ecspi();
 320
 321        /* DDR initialization */
 322        spl_dram_init();
 323
 324        /* Clear the BSS. */
 325        memset(__bss_start, 0, __bss_end - __bss_start);
 326
 327        displ5_set_iomux_misc_spl();
 328
 329        /* Initialize and reset WDT in SPL */
 330        hw_watchdog_init();
 331        WATCHDOG_RESET();
 332
 333        /* load/boot image from boot device */
 334        board_init_r(NULL, 0);
 335}
 336
 337#define EM_PAD IMX_GPIO_NR(3, 29)
 338int board_check_emergency_pad(void)
 339{
 340        int ret;
 341
 342        ret = gpio_direction_input(EM_PAD);
 343        if (ret)
 344                return ret;
 345
 346        return !gpio_get_value(EM_PAD);
 347}
 348
 349void board_boot_order(u32 *spl_boot_list)
 350{
 351        /* Default boot sequence SPI -> MMC */
 352        spl_boot_list[0] = spl_boot_device();
 353        spl_boot_list[1] = BOOT_DEVICE_MMC1;
 354        spl_boot_list[2] = BOOT_DEVICE_UART;
 355        spl_boot_list[3] = BOOT_DEVICE_NONE;
 356
 357        /*
 358         * In case of emergency PAD pressed, we always boot
 359         * to proper u-boot and perform recovery tasks there.
 360         */
 361        if (board_check_emergency_pad())
 362                return;
 363
 364#ifdef CONFIG_SPL_ENV_SUPPORT
 365        /* 'fastboot' */
 366        const char *s;
 367
 368        if (env_init() || env_load())
 369                return;
 370
 371        s = env_get("BOOT_FROM");
 372        if (s && !bootcount_error() && strcmp(s, "ACTIVE") == 0) {
 373                spl_boot_list[0] = BOOT_DEVICE_MMC1;
 374                spl_boot_list[1] = spl_boot_device();
 375        }
 376#endif
 377}
 378
 379void reset_cpu(void) {}
 380
 381#ifdef CONFIG_SPL_LOAD_FIT
 382int board_fit_config_name_match(const char *name)
 383{
 384        return 0;
 385}
 386#endif
 387
 388#ifdef CONFIG_SPL_OS_BOOT
 389/* Return: 1 - boot to U-Boot. 0 - boot OS (falcon mode) */
 390int spl_start_uboot(void)
 391{
 392        /* break into full u-boot on 'c' */
 393        if (serial_tstc() && serial_getc() == 'c')
 394                return 1;
 395
 396#ifdef CONFIG_SPL_ENV_SUPPORT
 397        if (env_get_yesno("boot_os") != 1)
 398                return 1;
 399#endif
 400        return 0;
 401}
 402#endif
 403