1 /* 2 * DHCOM DH-iMX6 PDK board support 3 * 4 * Copyright (C) 2017 Marek Vasut <marex@denx.de> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <asm/arch/clock.h> 11 #include <asm/arch/crm_regs.h> 12 #include <asm/arch/imx-regs.h> 13 #include <asm/arch/iomux.h> 14 #include <asm/arch/mx6-pins.h> 15 #include <asm/arch/sys_proto.h> 16 #include <asm/gpio.h> 17 #include <asm/io.h> 18 #include <asm/mach-imx/boot_mode.h> 19 #include <asm/mach-imx/iomux-v3.h> 20 #include <asm/mach-imx/mxc_i2c.h> 21 #include <asm/mach-imx/sata.h> 22 #include <environment.h> 23 #include <errno.h> 24 #include <fsl_esdhc.h> 25 #include <fuse.h> 26 #include <i2c.h> 27 #include <miiphy.h> 28 #include <mmc.h> 29 #include <net.h> 30 #include <netdev.h> 31 #include <usb.h> 32 #include <usb/ehci-ci.h> 33 34 DECLARE_GLOBAL_DATA_PTR; 35 36 #define I2C_PAD_CTRL \ 37 (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ 38 PAD_CTL_HYS | PAD_CTL_ODE | PAD_CTL_SRE_FAST) 39 40 #define EEPROM_I2C_ADDRESS 0x50 41 42 #define PC MUX_PAD_CTRL(I2C_PAD_CTRL) 43 44 static struct i2c_pads_info dh6sdl_i2c_pad_info0 = { 45 .scl = { 46 .i2c_mode = MX6DL_PAD_EIM_D21__I2C1_SCL | PC, 47 .gpio_mode = MX6DL_PAD_EIM_D21__GPIO3_IO21 | PC, 48 .gp = IMX_GPIO_NR(3, 21) 49 }, 50 .sda = { 51 .i2c_mode = MX6DL_PAD_EIM_D28__I2C1_SDA | PC, 52 .gpio_mode = MX6DL_PAD_EIM_D28__GPIO3_IO28 | PC, 53 .gp = IMX_GPIO_NR(3, 28) 54 } 55 }; 56 57 static struct i2c_pads_info dh6sdl_i2c_pad_info1 = { 58 .scl = { 59 .i2c_mode = MX6DL_PAD_KEY_COL3__I2C2_SCL | PC, 60 .gpio_mode = MX6DL_PAD_KEY_COL3__GPIO4_IO12 | PC, 61 .gp = IMX_GPIO_NR(4, 12) 62 }, 63 .sda = { 64 .i2c_mode = MX6DL_PAD_KEY_ROW3__I2C2_SDA | PC, 65 .gpio_mode = MX6DL_PAD_KEY_ROW3__GPIO4_IO13 | PC, 66 .gp = IMX_GPIO_NR(4, 13) 67 } 68 }; 69 70 static struct i2c_pads_info dh6sdl_i2c_pad_info2 = { 71 .scl = { 72 .i2c_mode = MX6DL_PAD_GPIO_3__I2C3_SCL | PC, 73 .gpio_mode = MX6DL_PAD_GPIO_3__GPIO1_IO03 | PC, 74 .gp = IMX_GPIO_NR(1, 3) 75 }, 76 .sda = { 77 .i2c_mode = MX6DL_PAD_GPIO_6__I2C3_SDA | PC, 78 .gpio_mode = MX6DL_PAD_GPIO_6__GPIO1_IO06 | PC, 79 .gp = IMX_GPIO_NR(1, 6) 80 } 81 }; 82 83 static struct i2c_pads_info dh6dq_i2c_pad_info0 = { 84 .scl = { 85 .i2c_mode = MX6Q_PAD_EIM_D21__I2C1_SCL | PC, 86 .gpio_mode = MX6Q_PAD_EIM_D21__GPIO3_IO21 | PC, 87 .gp = IMX_GPIO_NR(3, 21) 88 }, 89 .sda = { 90 .i2c_mode = MX6Q_PAD_EIM_D28__I2C1_SDA | PC, 91 .gpio_mode = MX6Q_PAD_EIM_D28__GPIO3_IO28 | PC, 92 .gp = IMX_GPIO_NR(3, 28) 93 } 94 }; 95 96 static struct i2c_pads_info dh6dq_i2c_pad_info1 = { 97 .scl = { 98 .i2c_mode = MX6Q_PAD_KEY_COL3__I2C2_SCL | PC, 99 .gpio_mode = MX6Q_PAD_KEY_COL3__GPIO4_IO12 | PC, 100 .gp = IMX_GPIO_NR(4, 12) 101 }, 102 .sda = { 103 .i2c_mode = MX6Q_PAD_KEY_ROW3__I2C2_SDA | PC, 104 .gpio_mode = MX6Q_PAD_KEY_ROW3__GPIO4_IO13 | PC, 105 .gp = IMX_GPIO_NR(4, 13) 106 } 107 }; 108 109 static struct i2c_pads_info dh6dq_i2c_pad_info2 = { 110 .scl = { 111 .i2c_mode = MX6Q_PAD_GPIO_3__I2C3_SCL | PC, 112 .gpio_mode = MX6Q_PAD_GPIO_3__GPIO1_IO03 | PC, 113 .gp = IMX_GPIO_NR(1, 3) 114 }, 115 .sda = { 116 .i2c_mode = MX6Q_PAD_GPIO_6__I2C3_SDA | PC, 117 .gpio_mode = MX6Q_PAD_GPIO_6__GPIO1_IO06 | PC, 118 .gp = IMX_GPIO_NR(1, 6) 119 } 120 }; 121 122 int dram_init(void) 123 { 124 gd->ram_size = imx_ddr_size(); 125 return 0; 126 } 127 128 /* 129 * Do not overwrite the console 130 * Use always serial for U-Boot console 131 */ 132 int overwrite_console(void) 133 { 134 return 1; 135 } 136 137 #ifdef CONFIG_FEC_MXC 138 static void eth_phy_reset(void) 139 { 140 /* Reset PHY */ 141 gpio_direction_output(IMX_GPIO_NR(5, 0) , 0); 142 udelay(500); 143 gpio_set_value(IMX_GPIO_NR(5, 0), 1); 144 145 /* Enable VIO */ 146 gpio_direction_output(IMX_GPIO_NR(1, 7) , 0); 147 148 /* 149 * KSZ9021 PHY needs at least 10 mSec after PHY reset 150 * is released to stabilize 151 */ 152 mdelay(10); 153 } 154 155 static int setup_fec_clock(void) 156 { 157 struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; 158 159 /* set gpr1[21] to select anatop clock */ 160 clrsetbits_le32(&iomuxc_regs->gpr[1], 0x1 << 21, 0x1 << 21); 161 162 return enable_fec_anatop_clock(0, ENET_50MHZ); 163 } 164 165 int board_eth_init(bd_t *bis) 166 { 167 uint32_t base = IMX_FEC_BASE; 168 struct mii_dev *bus = NULL; 169 struct phy_device *phydev = NULL; 170 171 setup_fec_clock(); 172 173 eth_phy_reset(); 174 175 bus = fec_get_miibus(base, -1); 176 if (!bus) 177 return -EINVAL; 178 179 /* Scan PHY 0 */ 180 phydev = phy_find_by_mask(bus, 0xf, PHY_INTERFACE_MODE_RGMII); 181 if (!phydev) { 182 printf("Ethernet PHY not found!\n"); 183 return -EINVAL; 184 } 185 186 return fec_probe(bis, -1, base, bus, phydev); 187 } 188 #endif 189 190 #ifdef CONFIG_FSL_ESDHC 191 192 #define USDHC2_CD_GPIO IMX_GPIO_NR(6, 16) 193 #define USDHC3_CD_GPIO IMX_GPIO_NR(7, 8) 194 195 static struct fsl_esdhc_cfg usdhc_cfg[3] = { 196 { USDHC2_BASE_ADDR }, 197 { USDHC3_BASE_ADDR }, 198 { USDHC4_BASE_ADDR }, 199 }; 200 201 int board_mmc_getcd(struct mmc *mmc) 202 { 203 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; 204 205 switch (cfg->esdhc_base) { 206 case USDHC2_BASE_ADDR: 207 return gpio_get_value(USDHC2_CD_GPIO); 208 case USDHC3_BASE_ADDR: 209 return !gpio_get_value(USDHC3_CD_GPIO); 210 case USDHC4_BASE_ADDR: 211 return 1; /* eMMC/uSDHC4 is always present */ 212 } 213 214 return 0; 215 } 216 217 int board_mmc_init(bd_t *bis) 218 { 219 int i, ret; 220 221 /* 222 * According to the board_mmc_init() the following map is done: 223 * (U-Boot device node) (Physical Port) 224 * mmc0 SD interface 225 * mmc1 micro SD 226 * mmc2 eMMC 227 */ 228 gpio_direction_input(USDHC2_CD_GPIO); 229 gpio_direction_input(USDHC3_CD_GPIO); 230 231 usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); 232 usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); 233 usdhc_cfg[2].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK); 234 235 for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) { 236 ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]); 237 if (ret) 238 return ret; 239 } 240 241 return 0; 242 } 243 #endif 244 245 #ifdef CONFIG_USB_EHCI_MX6 246 static void setup_usb(void) 247 { 248 /* 249 * Set daisy chain for otg_pin_id on MX6Q. 250 * For MX6DL, this bit is reserved. 251 */ 252 imx_iomux_set_gpr_register(1, 13, 1, 0); 253 } 254 255 int board_usb_phy_mode(int port) 256 { 257 if (port == 1) 258 return USB_INIT_HOST; 259 else 260 return USB_INIT_DEVICE; 261 } 262 263 int board_ehci_power(int port, int on) 264 { 265 switch (port) { 266 case 0: 267 break; 268 case 1: 269 gpio_direction_output(IMX_GPIO_NR(3, 31), !!on); 270 break; 271 default: 272 printf("MXC USB port %d not yet supported\n", port); 273 return -EINVAL; 274 } 275 276 return 0; 277 } 278 #endif 279 280 static int setup_dhcom_mac_from_fuse(void) 281 { 282 unsigned char enetaddr[6]; 283 int ret; 284 285 ret = eth_env_get_enetaddr("ethaddr", enetaddr); 286 if (ret) /* ethaddr is already set */ 287 return 0; 288 289 imx_get_mac_from_fuse(0, enetaddr); 290 291 if (is_valid_ethaddr(enetaddr)) { 292 eth_env_set_enetaddr("ethaddr", enetaddr); 293 return 0; 294 } 295 296 ret = i2c_set_bus_num(2); 297 if (ret) { 298 printf("Error switching I2C bus!\n"); 299 return ret; 300 } 301 302 ret = i2c_read(EEPROM_I2C_ADDRESS, 0xfa, 0x1, enetaddr, 0x6); 303 if (ret) { 304 printf("Error reading configuration EEPROM!\n"); 305 return ret; 306 } 307 308 if (is_valid_ethaddr(enetaddr)) 309 eth_env_set_enetaddr("ethaddr", enetaddr); 310 311 return 0; 312 } 313 314 int board_early_init_f(void) 315 { 316 #ifdef CONFIG_USB_EHCI_MX6 317 setup_usb(); 318 #endif 319 320 return 0; 321 } 322 323 #ifdef CONFIG_MXC_SPI 324 int board_spi_cs_gpio(unsigned bus, unsigned cs) 325 { 326 if (bus == 0 && cs == 0) 327 return IMX_GPIO_NR(2, 30); 328 else 329 return -1; 330 } 331 #endif 332 333 int board_init(void) 334 { 335 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 336 337 /* address of boot parameters */ 338 gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; 339 340 /* Enable eim_slow clocks */ 341 setbits_le32(&mxc_ccm->CCGR6, 0x1 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET); 342 343 #ifdef CONFIG_SYS_I2C_MXC 344 if (is_mx6dq()) { 345 setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info0); 346 setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info1); 347 setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info2); 348 } else { 349 setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info0); 350 setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info1); 351 setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info2); 352 } 353 #endif 354 355 #ifdef CONFIG_SATA 356 setup_sata(); 357 #endif 358 359 setup_dhcom_mac_from_fuse(); 360 361 return 0; 362 } 363 364 #ifdef CONFIG_CMD_BMODE 365 static const struct boot_mode board_boot_modes[] = { 366 /* 4 bit bus width */ 367 {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, 368 {"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, 369 /* 8 bit bus width */ 370 {"emmc", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, 371 {NULL, 0}, 372 }; 373 #endif 374 375 #define HW_CODE_BIT_0 IMX_GPIO_NR(2, 19) 376 #define HW_CODE_BIT_1 IMX_GPIO_NR(6, 6) 377 #define HW_CODE_BIT_2 IMX_GPIO_NR(2, 16) 378 379 static int board_get_hwcode(void) 380 { 381 int hw_code; 382 383 gpio_direction_input(HW_CODE_BIT_0); 384 gpio_direction_input(HW_CODE_BIT_1); 385 gpio_direction_input(HW_CODE_BIT_2); 386 387 /* HW 100 + HW 200 = 00b; HW 300 = 01b */ 388 hw_code = ((gpio_get_value(HW_CODE_BIT_2) << 2) | 389 (gpio_get_value(HW_CODE_BIT_1) << 1) | 390 gpio_get_value(HW_CODE_BIT_0)) + 2; 391 392 return hw_code; 393 } 394 395 int board_late_init(void) 396 { 397 u32 hw_code; 398 char buf[16]; 399 400 hw_code = board_get_hwcode(); 401 402 switch (get_cpu_type()) { 403 case MXC_CPU_MX6SOLO: 404 snprintf(buf, sizeof(buf), "imx6s-dhcom%1d", hw_code); 405 break; 406 case MXC_CPU_MX6DL: 407 snprintf(buf, sizeof(buf), "imx6dl-dhcom%1d", hw_code); 408 break; 409 case MXC_CPU_MX6D: 410 snprintf(buf, sizeof(buf), "imx6d-dhcom%1d", hw_code); 411 break; 412 case MXC_CPU_MX6Q: 413 snprintf(buf, sizeof(buf), "imx6q-dhcom%1d", hw_code); 414 break; 415 default: 416 snprintf(buf, sizeof(buf), "UNKNOWN%1d", hw_code); 417 break; 418 } 419 420 env_set("dhcom", buf); 421 422 #ifdef CONFIG_CMD_BMODE 423 add_board_boot_modes(board_boot_modes); 424 #endif 425 return 0; 426 } 427 428 int checkboard(void) 429 { 430 puts("Board: DHCOM i.MX6\n"); 431 return 0; 432 } 433