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