1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2016 Amarula Solutions B.V. 4 * Copyright (C) 2016 Engicam S.r.l. 5 * Author: Jagan Teki <jagan@amarulasolutions.com> 6 */ 7 8#include <common.h> 9#include <command.h> 10#include <env.h> 11#include <hang.h> 12#include <init.h> 13#include <log.h> 14#include <mmc.h> 15#include <asm/arch/clock.h> 16#include <asm/arch/imx-regs.h> 17#include <asm/arch/sys_proto.h> 18#include <watchdog.h> 19#include <asm/global_data.h> 20 21#include "board.h" 22 23DECLARE_GLOBAL_DATA_PTR; 24 25#ifdef CONFIG_ENV_IS_IN_MMC 26static void mmc_late_init(void) 27{ 28 char cmd[32]; 29 char mmcblk[32]; 30 u32 dev_no = mmc_get_env_dev(); 31 32 env_set_ulong("mmcdev", dev_no); 33 34 /* Set mmcblk env */ 35 sprintf(mmcblk, "/dev/mmcblk%dp2 rootwait rw", dev_no); 36 env_set("mmcroot", mmcblk); 37 38 sprintf(cmd, "mmc dev %d", dev_no); 39 run_command(cmd, 0); 40} 41#endif 42 43enum engicam_boards { 44 IMX6Q_ICORE, 45 IMX6DL_ICORE, 46 IMX6Q_ICORE_MIPI, 47 IMX6DL_ICORE_MIPI, 48 IMX6Q_ICORE_RQS, 49 IMX6DL_ICORE_RQS, 50 IMX6UL_GEAM, 51 IMX6UL_ISIOT_EMMC, 52 IMX6UL_ISIOT_NAND, 53 ENGICAM_BOARDS, 54}; 55 56static const char * const board_fdt_file[ENGICAM_BOARDS] = { 57 [IMX6Q_ICORE] = "imx6q-icore.dtb", 58 [IMX6DL_ICORE] = "imx6dl-icore.dtb", 59 [IMX6Q_ICORE_MIPI] = "imx6q-icore-mipi.dtb", 60 [IMX6DL_ICORE_MIPI] = "imx6dl-icore-mipi.dtb", 61 [IMX6Q_ICORE_RQS] = "imx6q-icore-rqs.dtb", 62 [IMX6DL_ICORE_RQS] = "imx6dl-icore-rqs.dtb", 63 [IMX6UL_GEAM] = "imx6ul-geam.dtb", 64 [IMX6UL_ISIOT_EMMC] = "imx6ul-isiot-emmc.dtb", 65 [IMX6UL_ISIOT_NAND] = "imx6ul-isiot-nand.dtb", 66}; 67 68static int setenv_fdt_file(int board_detected) 69{ 70 if (board_detected < 0 || board_detected >= ENGICAM_BOARDS) 71 return -EINVAL; 72 73 if (!board_fdt_file[board_detected]) 74 return -ENODEV; 75 76 env_set("fdt_file", board_fdt_file[board_detected]); 77 return 0; 78} 79 80static enum engicam_boards engicam_board_detect(void) 81{ 82 const char *cmp_dtb = CONFIG_DEFAULT_DEVICE_TREE; 83 84 if (!strcmp(cmp_dtb, "imx6q-icore")) { 85 if (is_mx6dq()) 86 return IMX6Q_ICORE; 87 else if (is_mx6dl() || is_mx6solo()) 88 return IMX6DL_ICORE; 89 } else if (!strcmp(cmp_dtb, "imx6q-icore-mipi")) { 90 if (is_mx6dq()) 91 return IMX6Q_ICORE_MIPI; 92 else if (is_mx6dl() || is_mx6solo()) 93 return IMX6DL_ICORE_MIPI; 94 } else if (!strcmp(cmp_dtb, "imx6q-icore-rqs")) { 95 if (is_mx6dq()) 96 return IMX6Q_ICORE_RQS; 97 else if (is_mx6dl() || is_mx6solo()) 98 return IMX6DL_ICORE_RQS; 99 } else if (!strcmp(cmp_dtb, "imx6ul-geam")) 100 return IMX6UL_GEAM; 101 else if (!strcmp(cmp_dtb, "imx6ul-isiot-emmc")) 102 return IMX6UL_ISIOT_EMMC; 103 else if (!strcmp(cmp_dtb, "imx6ul-isiot-nand")) 104 return IMX6UL_ISIOT_NAND; 105 106 return -EINVAL; 107} 108 109static int fixup_enet_clock(enum engicam_boards board_detected) 110{ 111 struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; 112 int clk_internal = 0; 113 114 switch (board_detected) { 115 case IMX6Q_ICORE_MIPI: 116 case IMX6DL_ICORE_MIPI: 117 clk_internal = 1; 118 break; 119 default: 120 break; 121 } 122 123 /* set gpr1[21] to select anatop clock */ 124 debug("fixup_enet_clock %d\n", clk_internal); 125 clrsetbits_le32(&iomuxc_regs->gpr[1], 0x1 << 21, clk_internal << 21); 126 127 if (!clk_internal) { 128 /* clock is external */ 129 return 0; 130 } 131 132 return enable_fec_anatop_clock(0, ENET_50MHZ); 133} 134 135int board_late_init(void) 136{ 137 enum engicam_boards board_detected = IMX6Q_ICORE; 138 139 switch ((imx6_src_get_boot_mode() & IMX6_BMODE_MASK) >> 140 IMX6_BMODE_SHIFT) { 141 case IMX6_BMODE_SD: 142 case IMX6_BMODE_ESD: 143 case IMX6_BMODE_MMC: 144 case IMX6_BMODE_EMMC: 145#ifdef CONFIG_ENV_IS_IN_MMC 146 mmc_late_init(); 147#endif 148 env_set("modeboot", "mmcboot"); 149 break; 150 case IMX6_BMODE_NAND_MIN ... IMX6_BMODE_NAND_MAX: 151 env_set("modeboot", "nandboot"); 152 break; 153 default: 154 env_set("modeboot", ""); 155 break; 156 } 157 158 if (is_mx6ul()) 159 env_set("console", "ttymxc0"); 160 else 161 env_set("console", "ttymxc3"); 162 163 board_detected = engicam_board_detect(); 164 if (board_detected < 0) 165 hang(); 166 167 fixup_enet_clock(board_detected); 168 setenv_fdt_file(board_detected); 169 170#ifdef CONFIG_HW_WATCHDOG 171 hw_watchdog_init(); 172#endif 173 174 return 0; 175} 176 177int board_init(void) 178{ 179 /* Address of boot parameters */ 180 gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; 181 182#ifdef CONFIG_NAND_MXS 183 setup_gpmi_nand(); 184#endif 185 186#ifdef CONFIG_VIDEO_IPUV3 187 setup_display(); 188#endif 189 190 return 0; 191} 192 193int dram_init(void) 194{ 195 gd->ram_size = imx_ddr_size(); 196 197 return 0; 198} 199