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