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 if (port == 1) 257 return USB_INIT_HOST; 258 else 259 return USB_INIT_DEVICE; 260 } 261 262 int board_ehci_power(int port, int on) 263 { 264 switch (port) { 265 case 0: 266 break; 267 case 1: 268 gpio_direction_output(IMX_GPIO_NR(3, 31), !!on); 269 break; 270 default: 271 printf("MXC USB port %d not yet supported\n", port); 272 return -EINVAL; 273 } 274 275 return 0; 276 } 277 #endif 278 279 static int setup_dhcom_mac_from_fuse(void) 280 { 281 unsigned char enetaddr[6]; 282 int ret; 283 284 ret = eth_env_get_enetaddr("ethaddr", enetaddr); 285 if (ret) /* ethaddr is already set */ 286 return 0; 287 288 imx_get_mac_from_fuse(0, enetaddr); 289 290 if (is_valid_ethaddr(enetaddr)) { 291 eth_env_set_enetaddr("ethaddr", enetaddr); 292 return 0; 293 } 294 295 ret = i2c_set_bus_num(2); 296 if (ret) { 297 printf("Error switching I2C bus!\n"); 298 return ret; 299 } 300 301 ret = i2c_read(EEPROM_I2C_ADDRESS, 0xfa, 0x1, enetaddr, 0x6); 302 if (ret) { 303 printf("Error reading configuration EEPROM!\n"); 304 return ret; 305 } 306 307 if (is_valid_ethaddr(enetaddr)) 308 eth_env_set_enetaddr("ethaddr", enetaddr); 309 310 return 0; 311 } 312 313 int board_early_init_f(void) 314 { 315 #ifdef CONFIG_USB_EHCI_MX6 316 setup_usb(); 317 #endif 318 319 return 0; 320 } 321 322 #ifdef CONFIG_MXC_SPI 323 int board_spi_cs_gpio(unsigned bus, unsigned cs) 324 { 325 if (bus == 0 && cs == 0) 326 return IMX_GPIO_NR(2, 30); 327 else 328 return -1; 329 } 330 #endif 331 332 int board_init(void) 333 { 334 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 335 336 /* address of boot parameters */ 337 gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; 338 339 /* Enable eim_slow clocks */ 340 setbits_le32(&mxc_ccm->CCGR6, 0x1 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET); 341 342 #ifdef CONFIG_SYS_I2C_MXC 343 if (is_mx6dq()) { 344 setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info0); 345 setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info1); 346 setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info2); 347 } else { 348 setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info0); 349 setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info1); 350 setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info2); 351 } 352 #endif 353 354 #ifdef CONFIG_SATA 355 setup_sata(); 356 #endif 357 358 setup_dhcom_mac_from_fuse(); 359 360 return 0; 361 } 362 363 #ifdef CONFIG_CMD_BMODE 364 static const struct boot_mode board_boot_modes[] = { 365 /* 4 bit bus width */ 366 {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, 367 {"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, 368 /* 8 bit bus width */ 369 {"emmc", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, 370 {NULL, 0}, 371 }; 372 #endif 373 374 #define HW_CODE_BIT_0 IMX_GPIO_NR(2, 19) 375 #define HW_CODE_BIT_1 IMX_GPIO_NR(6, 6) 376 #define HW_CODE_BIT_2 IMX_GPIO_NR(2, 16) 377 378 static int board_get_hwcode(void) 379 { 380 int hw_code; 381 382 gpio_direction_input(HW_CODE_BIT_0); 383 gpio_direction_input(HW_CODE_BIT_1); 384 gpio_direction_input(HW_CODE_BIT_2); 385 386 /* HW 100 + HW 200 = 00b; HW 300 = 01b */ 387 hw_code = ((gpio_get_value(HW_CODE_BIT_2) << 2) | 388 (gpio_get_value(HW_CODE_BIT_1) << 1) | 389 gpio_get_value(HW_CODE_BIT_0)) + 2; 390 391 return hw_code; 392 } 393 394 int board_late_init(void) 395 { 396 u32 hw_code; 397 char buf[16]; 398 399 hw_code = board_get_hwcode(); 400 401 switch (get_cpu_type()) { 402 case MXC_CPU_MX6SOLO: 403 snprintf(buf, sizeof(buf), "imx6s-dhcom%1d", hw_code); 404 break; 405 case MXC_CPU_MX6DL: 406 snprintf(buf, sizeof(buf), "imx6dl-dhcom%1d", hw_code); 407 break; 408 case MXC_CPU_MX6D: 409 snprintf(buf, sizeof(buf), "imx6d-dhcom%1d", hw_code); 410 break; 411 case MXC_CPU_MX6Q: 412 snprintf(buf, sizeof(buf), "imx6q-dhcom%1d", hw_code); 413 break; 414 default: 415 snprintf(buf, sizeof(buf), "UNKNOWN%1d", hw_code); 416 break; 417 } 418 419 env_set("dhcom", buf); 420 421 #ifdef CONFIG_CMD_BMODE 422 add_board_boot_modes(board_boot_modes); 423 #endif 424 return 0; 425 } 426 427 int checkboard(void) 428 { 429 puts("Board: DHCOM i.MX6\n"); 430 return 0; 431 } 432