1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * DHCOM DH-iMX6 PDK board support 4 * 5 * Copyright (C) 2017 Marek Vasut <marex@denx.de> 6 */ 7 8#include <dm.h> 9#include <image.h> 10#include <init.h> 11#include <net.h> 12#include <asm/global_data.h> 13#include <dm/device-internal.h> 14#include <asm/arch/clock.h> 15#include <asm/arch/crm_regs.h> 16#include <asm/arch/imx-regs.h> 17#include <asm/arch/iomux.h> 18#include <asm/arch/mx6-pins.h> 19#include <asm/arch/sys_proto.h> 20#include <asm/gpio.h> 21#include <asm/io.h> 22#include <asm/mach-imx/boot_mode.h> 23#include <asm/mach-imx/iomux-v3.h> 24#include <asm/mach-imx/sata.h> 25#include <ahci.h> 26#include <dwc_ahsata.h> 27#include <env.h> 28#include <errno.h> 29#include <fsl_esdhc_imx.h> 30#include <fuse.h> 31#include <i2c_eeprom.h> 32#include <mmc.h> 33#include <usb.h> 34#include <linux/delay.h> 35#include <usb/ehci-ci.h> 36 37#include "../common/dh_common.h" 38#include "../common/dh_imx.h" 39 40DECLARE_GLOBAL_DATA_PTR; 41 42int dram_init(void) 43{ 44 gd->ram_size = imx_ddr_size(); 45 return 0; 46} 47 48/* 49 * Do not overwrite the console 50 * Use always serial for U-Boot console 51 */ 52int overwrite_console(void) 53{ 54 return 1; 55} 56 57static int setup_fec_clock(void) 58{ 59 struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; 60 61 /* set gpr1[21] to select anatop clock */ 62 clrsetbits_le32(&iomuxc_regs->gpr[1], 0x1 << 21, 0x1 << 21); 63 64 return enable_fec_anatop_clock(0, ENET_50MHZ); 65} 66 67#ifdef CONFIG_USB_EHCI_MX6 68static void setup_usb(void) 69{ 70 /* 71 * Set daisy chain for otg_pin_id on MX6Q. 72 * For MX6DL, this bit is reserved. 73 */ 74 imx_iomux_set_gpr_register(1, 13, 1, 0); 75} 76 77int board_usb_phy_mode(int port) 78{ 79 if (port == 1) 80 return USB_INIT_HOST; 81 else 82 return USB_INIT_DEVICE; 83} 84#endif 85 86int dh_setup_mac_address(void) 87{ 88 unsigned char enetaddr[6]; 89 90 if (dh_mac_is_in_env("ethaddr")) 91 return 0; 92 93 if (dh_get_mac_is_enabled("ethernet0")) 94 return 0; 95 96 if (!dh_imx_get_mac_from_fuse(enetaddr)) 97 goto out; 98 99 if (!dh_get_mac_from_eeprom(enetaddr, "eeprom0")) 100 goto out; 101 102 printf("%s: Unable to get MAC address!\n", __func__); 103 return -ENXIO; 104 105out: 106 return eth_env_set_enetaddr("ethaddr", enetaddr); 107} 108 109int board_early_init_f(void) 110{ 111#ifdef CONFIG_USB_EHCI_MX6 112 setup_usb(); 113#endif 114 115 return 0; 116} 117 118int board_init(void) 119{ 120 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 121 122 /* address of boot parameters */ 123 gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; 124 125 /* Enable eim_slow clocks */ 126 setbits_le32(&mxc_ccm->CCGR6, 0x1 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET); 127 128 setup_fec_clock(); 129 130 return 0; 131} 132 133#ifdef CONFIG_CMD_BMODE 134static const struct boot_mode board_boot_modes[] = { 135 /* 4 bit bus width */ 136 {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, 137 {"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, 138 /* 8 bit bus width */ 139 {"emmc", MAKE_CFGVAL(0x60, 0x58, 0x00, 0x00)}, 140 {NULL, 0}, 141}; 142#endif 143 144#define HW_CODE_BIT_0 IMX_GPIO_NR(2, 19) 145#define HW_CODE_BIT_1 IMX_GPIO_NR(6, 6) 146#define HW_CODE_BIT_2 IMX_GPIO_NR(2, 16) 147 148static int board_get_hwcode(void) 149{ 150 int hw_code; 151 152 gpio_request(HW_CODE_BIT_0, "HW-code-bit-0"); 153 gpio_request(HW_CODE_BIT_1, "HW-code-bit-1"); 154 gpio_request(HW_CODE_BIT_2, "HW-code-bit-2"); 155 156 gpio_direction_input(HW_CODE_BIT_0); 157 gpio_direction_input(HW_CODE_BIT_1); 158 gpio_direction_input(HW_CODE_BIT_2); 159 160 /* HW 100 + HW 200 = 00b; HW 300 = 01b */ 161 hw_code = ((gpio_get_value(HW_CODE_BIT_2) << 2) | 162 (gpio_get_value(HW_CODE_BIT_1) << 1) | 163 gpio_get_value(HW_CODE_BIT_0)) + 2; 164 165 return hw_code; 166} 167 168int board_late_init(void) 169{ 170 u32 hw_code; 171 char buf[16]; 172 173 dh_setup_mac_address(); 174 175 hw_code = board_get_hwcode(); 176 177 switch (get_cpu_type()) { 178 case MXC_CPU_MX6SOLO: 179 snprintf(buf, sizeof(buf), "imx6s-dhcom%1d", hw_code); 180 break; 181 case MXC_CPU_MX6DL: 182 snprintf(buf, sizeof(buf), "imx6dl-dhcom%1d", hw_code); 183 break; 184 case MXC_CPU_MX6D: 185 snprintf(buf, sizeof(buf), "imx6d-dhcom%1d", hw_code); 186 break; 187 case MXC_CPU_MX6Q: 188 snprintf(buf, sizeof(buf), "imx6q-dhcom%1d", hw_code); 189 break; 190 default: 191 snprintf(buf, sizeof(buf), "UNKNOWN%1d", hw_code); 192 break; 193 } 194 195 env_set("dhcom", buf); 196 197#ifdef CONFIG_CMD_BMODE 198 add_board_boot_modes(board_boot_modes); 199#endif 200 return 0; 201} 202 203int checkboard(void) 204{ 205 puts("Board: DHCOM i.MX6\n"); 206 return 0; 207} 208 209#ifdef CONFIG_MULTI_DTB_FIT 210static int strcmp_prefix(const char *s1, const char *s2) 211{ 212 size_t n; 213 214 n = min(strlen(s1), strlen(s2)); 215 return strncmp(s1, s2, n); 216} 217 218int board_fit_config_name_match(const char *name) 219{ 220 char *want; 221 char *have; 222 223 /* Test Board suffix, e.g. -dhcom-drc02 */ 224 want = strchr(CONFIG_DEFAULT_DEVICE_TREE, '-'); 225 have = strchr(name, '-'); 226 227 if (!want || !have || strcmp(want, have)) 228 return -EINVAL; 229 230 /* Test SoC prefix */ 231 if (is_mx6dq() && !strcmp_prefix(name, "imx6q-")) 232 return 0; 233 234 if (is_mx6sdl()) { 235 if (!strcmp_prefix(name, "imx6s-") || !strcmp_prefix(name, "imx6dl-")) 236 return 0; 237 } 238 239 return -EINVAL; 240} 241#endif 242