1 /* 2 * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. 3 * Copyright (C) 2013, Boundary Devices <info@boundarydevices.com> 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <common.h> 25 #include <asm/io.h> 26 #include <asm/arch/clock.h> 27 #include <asm/arch/imx-regs.h> 28 #include <asm/arch/iomux.h> 29 #include <asm/arch/sys_proto.h> 30 #include <malloc.h> 31 #include <asm/arch/mx6-pins.h> 32 #include <asm/errno.h> 33 #include <asm/gpio.h> 34 #include <asm/imx-common/iomux-v3.h> 35 #include <asm/imx-common/mxc_i2c.h> 36 #include <asm/imx-common/boot_mode.h> 37 #include <mmc.h> 38 #include <fsl_esdhc.h> 39 #include <micrel.h> 40 #include <miiphy.h> 41 #include <netdev.h> 42 #include <linux/fb.h> 43 #include <ipu_pixfmt.h> 44 #include <asm/arch/crm_regs.h> 45 #include <asm/arch/mxc_hdmi.h> 46 #include <i2c.h> 47 48 DECLARE_GLOBAL_DATA_PTR; 49 50 #define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ 51 PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 52 PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) 53 54 #define USDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ 55 PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ 56 PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) 57 58 #define ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ 59 PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 60 PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 61 62 #define SPI_PAD_CTRL (PAD_CTL_HYS | \ 63 PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_MED | \ 64 PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) 65 66 #define BUTTON_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ 67 PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 68 PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 69 70 #define I2C_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ 71 PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 72 PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ 73 PAD_CTL_ODE | PAD_CTL_SRE_FAST) 74 75 #define WEAK_PULLUP (PAD_CTL_PKE | PAD_CTL_PUE | \ 76 PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 77 PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ 78 PAD_CTL_SRE_SLOW) 79 80 #define WEAK_PULLDOWN (PAD_CTL_PKE | PAD_CTL_PUE | \ 81 PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_MED | \ 82 PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ 83 PAD_CTL_SRE_SLOW) 84 85 #define OUTPUT_40OHM (PAD_CTL_SPEED_MED|PAD_CTL_DSE_40ohm) 86 87 int dram_init(void) 88 { 89 gd->ram_size = ((ulong)CONFIG_DDR_MB * 1024 * 1024); 90 91 return 0; 92 } 93 94 iomux_v3_cfg_t const uart1_pads[] = { 95 MX6_PAD_SD3_DAT6__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL), 96 MX6_PAD_SD3_DAT7__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL), 97 }; 98 99 iomux_v3_cfg_t const uart2_pads[] = { 100 MX6_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL), 101 MX6_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL), 102 }; 103 104 #define PC MUX_PAD_CTRL(I2C_PAD_CTRL) 105 106 /* I2C1, SGTL5000 */ 107 struct i2c_pads_info i2c_pad_info0 = { 108 .scl = { 109 .i2c_mode = MX6_PAD_EIM_D21__I2C1_SCL | PC, 110 .gpio_mode = MX6_PAD_EIM_D21__GPIO_3_21 | PC, 111 .gp = IMX_GPIO_NR(3, 21) 112 }, 113 .sda = { 114 .i2c_mode = MX6_PAD_EIM_D28__I2C1_SDA | PC, 115 .gpio_mode = MX6_PAD_EIM_D28__GPIO_3_28 | PC, 116 .gp = IMX_GPIO_NR(3, 28) 117 } 118 }; 119 120 /* I2C2 Camera, MIPI */ 121 struct i2c_pads_info i2c_pad_info1 = { 122 .scl = { 123 .i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | PC, 124 .gpio_mode = MX6_PAD_KEY_COL3__GPIO_4_12 | PC, 125 .gp = IMX_GPIO_NR(4, 12) 126 }, 127 .sda = { 128 .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC, 129 .gpio_mode = MX6_PAD_KEY_ROW3__GPIO_4_13 | PC, 130 .gp = IMX_GPIO_NR(4, 13) 131 } 132 }; 133 134 /* I2C3, J15 - RGB connector */ 135 struct i2c_pads_info i2c_pad_info2 = { 136 .scl = { 137 .i2c_mode = MX6_PAD_GPIO_5__I2C3_SCL | PC, 138 .gpio_mode = MX6_PAD_GPIO_5__GPIO_1_5 | PC, 139 .gp = IMX_GPIO_NR(1, 5) 140 }, 141 .sda = { 142 .i2c_mode = MX6_PAD_GPIO_16__I2C3_SDA | PC, 143 .gpio_mode = MX6_PAD_GPIO_16__GPIO_7_11 | PC, 144 .gp = IMX_GPIO_NR(7, 11) 145 } 146 }; 147 148 iomux_v3_cfg_t const usdhc3_pads[] = { 149 MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), 150 MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), 151 MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), 152 MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), 153 MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), 154 MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), 155 MX6_PAD_SD3_DAT5__GPIO_7_0 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */ 156 }; 157 158 iomux_v3_cfg_t const usdhc4_pads[] = { 159 MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), 160 MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), 161 MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), 162 MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), 163 MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), 164 MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), 165 MX6_PAD_NANDF_D6__GPIO_2_6 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */ 166 }; 167 168 iomux_v3_cfg_t const enet_pads1[] = { 169 MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), 170 MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), 171 MX6_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL), 172 MX6_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), 173 MX6_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), 174 MX6_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), 175 MX6_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), 176 MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), 177 MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL), 178 /* pin 35 - 1 (PHY_AD2) on reset */ 179 MX6_PAD_RGMII_RXC__GPIO_6_30 | MUX_PAD_CTRL(NO_PAD_CTRL), 180 /* pin 32 - 1 - (MODE0) all */ 181 MX6_PAD_RGMII_RD0__GPIO_6_25 | MUX_PAD_CTRL(NO_PAD_CTRL), 182 /* pin 31 - 1 - (MODE1) all */ 183 MX6_PAD_RGMII_RD1__GPIO_6_27 | MUX_PAD_CTRL(NO_PAD_CTRL), 184 /* pin 28 - 1 - (MODE2) all */ 185 MX6_PAD_RGMII_RD2__GPIO_6_28 | MUX_PAD_CTRL(NO_PAD_CTRL), 186 /* pin 27 - 1 - (MODE3) all */ 187 MX6_PAD_RGMII_RD3__GPIO_6_29 | MUX_PAD_CTRL(NO_PAD_CTRL), 188 /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */ 189 MX6_PAD_RGMII_RX_CTL__GPIO_6_24 | MUX_PAD_CTRL(NO_PAD_CTRL), 190 /* pin 42 PHY nRST */ 191 MX6_PAD_EIM_D23__GPIO_3_23 | MUX_PAD_CTRL(NO_PAD_CTRL), 192 MX6_PAD_ENET_RXD0__GPIO_1_27 | MUX_PAD_CTRL(NO_PAD_CTRL), 193 }; 194 195 iomux_v3_cfg_t const enet_pads2[] = { 196 MX6_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL), 197 MX6_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), 198 MX6_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), 199 MX6_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), 200 MX6_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), 201 MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), 202 }; 203 204 /* wl1271 pads on nitrogen6x */ 205 iomux_v3_cfg_t const wl12xx_pads[] = { 206 (MX6_PAD_NANDF_CS1__GPIO_6_14 & ~MUX_PAD_CTRL_MASK) 207 | MUX_PAD_CTRL(WEAK_PULLDOWN), 208 (MX6_PAD_NANDF_CS2__GPIO_6_15 & ~MUX_PAD_CTRL_MASK) 209 | MUX_PAD_CTRL(OUTPUT_40OHM), 210 (MX6_PAD_NANDF_CS3__GPIO_6_16 & ~MUX_PAD_CTRL_MASK) 211 | MUX_PAD_CTRL(OUTPUT_40OHM), 212 }; 213 #define WL12XX_WL_IRQ_GP IMX_GPIO_NR(6, 14) 214 #define WL12XX_WL_ENABLE_GP IMX_GPIO_NR(6, 15) 215 #define WL12XX_BT_ENABLE_GP IMX_GPIO_NR(6, 16) 216 217 /* Button assignments for J14 */ 218 static iomux_v3_cfg_t const button_pads[] = { 219 /* Menu */ 220 MX6_PAD_NANDF_D1__GPIO_2_1 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), 221 /* Back */ 222 MX6_PAD_NANDF_D2__GPIO_2_2 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), 223 /* Labelled Search (mapped to Power under Android) */ 224 MX6_PAD_NANDF_D3__GPIO_2_3 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), 225 /* Home */ 226 MX6_PAD_NANDF_D4__GPIO_2_4 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), 227 /* Volume Down */ 228 MX6_PAD_GPIO_19__GPIO_4_5 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), 229 /* Volume Up */ 230 MX6_PAD_GPIO_18__GPIO_7_13 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), 231 }; 232 233 static void setup_iomux_enet(void) 234 { 235 gpio_direction_output(IMX_GPIO_NR(3, 23), 0); /* SABRE Lite PHY rst */ 236 gpio_direction_output(IMX_GPIO_NR(1, 27), 0); /* Nitrogen6X PHY rst */ 237 gpio_direction_output(IMX_GPIO_NR(6, 30), 1); 238 gpio_direction_output(IMX_GPIO_NR(6, 25), 1); 239 gpio_direction_output(IMX_GPIO_NR(6, 27), 1); 240 gpio_direction_output(IMX_GPIO_NR(6, 28), 1); 241 gpio_direction_output(IMX_GPIO_NR(6, 29), 1); 242 imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1)); 243 gpio_direction_output(IMX_GPIO_NR(6, 24), 1); 244 245 /* Need delay 10ms according to KSZ9021 spec */ 246 udelay(1000 * 10); 247 gpio_set_value(IMX_GPIO_NR(3, 23), 1); /* SABRE Lite PHY reset */ 248 gpio_set_value(IMX_GPIO_NR(1, 27), 1); /* Nitrogen6X PHY reset */ 249 250 imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2)); 251 } 252 253 iomux_v3_cfg_t const usb_pads[] = { 254 MX6_PAD_GPIO_17__GPIO_7_12 | MUX_PAD_CTRL(NO_PAD_CTRL), 255 }; 256 257 static void setup_iomux_uart(void) 258 { 259 imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads)); 260 imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads)); 261 } 262 263 #ifdef CONFIG_USB_EHCI_MX6 264 int board_ehci_hcd_init(int port) 265 { 266 imx_iomux_v3_setup_multiple_pads(usb_pads, ARRAY_SIZE(usb_pads)); 267 268 /* Reset USB hub */ 269 gpio_direction_output(IMX_GPIO_NR(7, 12), 0); 270 mdelay(2); 271 gpio_set_value(IMX_GPIO_NR(7, 12), 1); 272 273 return 0; 274 } 275 #endif 276 277 #ifdef CONFIG_FSL_ESDHC 278 struct fsl_esdhc_cfg usdhc_cfg[2] = { 279 {USDHC3_BASE_ADDR}, 280 {USDHC4_BASE_ADDR}, 281 }; 282 283 int board_mmc_getcd(struct mmc *mmc) 284 { 285 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; 286 int ret; 287 288 if (cfg->esdhc_base == USDHC3_BASE_ADDR) { 289 gpio_direction_input(IMX_GPIO_NR(7, 0)); 290 ret = !gpio_get_value(IMX_GPIO_NR(7, 0)); 291 } else { 292 gpio_direction_input(IMX_GPIO_NR(2, 6)); 293 ret = !gpio_get_value(IMX_GPIO_NR(2, 6)); 294 } 295 296 return ret; 297 } 298 299 int board_mmc_init(bd_t *bis) 300 { 301 s32 status = 0; 302 u32 index = 0; 303 304 usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); 305 usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK); 306 307 for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) { 308 switch (index) { 309 case 0: 310 imx_iomux_v3_setup_multiple_pads( 311 usdhc3_pads, ARRAY_SIZE(usdhc3_pads)); 312 break; 313 case 1: 314 imx_iomux_v3_setup_multiple_pads( 315 usdhc4_pads, ARRAY_SIZE(usdhc4_pads)); 316 break; 317 default: 318 printf("Warning: you configured more USDHC controllers" 319 "(%d) then supported by the board (%d)\n", 320 index + 1, CONFIG_SYS_FSL_USDHC_NUM); 321 return status; 322 } 323 324 status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]); 325 } 326 327 return status; 328 } 329 #endif 330 331 u32 get_board_rev(void) 332 { 333 return 0x63000; 334 } 335 336 #ifdef CONFIG_MXC_SPI 337 iomux_v3_cfg_t const ecspi1_pads[] = { 338 /* SS1 */ 339 MX6_PAD_EIM_D19__GPIO_3_19 | MUX_PAD_CTRL(SPI_PAD_CTRL), 340 MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL), 341 MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL), 342 MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL), 343 }; 344 345 void setup_spi(void) 346 { 347 gpio_direction_output(CONFIG_SF_DEFAULT_CS, 1); 348 imx_iomux_v3_setup_multiple_pads(ecspi1_pads, 349 ARRAY_SIZE(ecspi1_pads)); 350 } 351 #endif 352 353 int board_phy_config(struct phy_device *phydev) 354 { 355 /* min rx data delay */ 356 ksz9021_phy_extended_write(phydev, 357 MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0x0); 358 /* min tx data delay */ 359 ksz9021_phy_extended_write(phydev, 360 MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0x0); 361 /* max rx/tx clock delay, min rx/tx control */ 362 ksz9021_phy_extended_write(phydev, 363 MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0xf0f0); 364 if (phydev->drv->config) 365 phydev->drv->config(phydev); 366 367 return 0; 368 } 369 370 int board_eth_init(bd_t *bis) 371 { 372 uint32_t base = IMX_FEC_BASE; 373 struct mii_dev *bus = NULL; 374 struct phy_device *phydev = NULL; 375 int ret; 376 377 setup_iomux_enet(); 378 379 #ifdef CONFIG_FEC_MXC 380 bus = fec_get_miibus(base, -1); 381 if (!bus) 382 return 0; 383 /* scan phy 4,5,6,7 */ 384 phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII); 385 if (!phydev) { 386 free(bus); 387 return 0; 388 } 389 printf("using phy at %d\n", phydev->addr); 390 ret = fec_probe(bis, -1, base, bus, phydev); 391 if (ret) { 392 printf("FEC MXC: %s:failed\n", __func__); 393 free(phydev); 394 free(bus); 395 } 396 #endif 397 return 0; 398 } 399 400 static void setup_buttons(void) 401 { 402 imx_iomux_v3_setup_multiple_pads(button_pads, 403 ARRAY_SIZE(button_pads)); 404 } 405 406 #ifdef CONFIG_CMD_SATA 407 408 int setup_sata(void) 409 { 410 struct iomuxc_base_regs *const iomuxc_regs 411 = (struct iomuxc_base_regs *) IOMUXC_BASE_ADDR; 412 int ret = enable_sata_clock(); 413 if (ret) 414 return ret; 415 416 clrsetbits_le32(&iomuxc_regs->gpr[13], 417 IOMUXC_GPR13_SATA_MASK, 418 IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB 419 |IOMUXC_GPR13_SATA_PHY_7_SATA2M 420 |IOMUXC_GPR13_SATA_SPEED_3G 421 |(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT) 422 |IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED 423 |IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16 424 |IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB 425 |IOMUXC_GPR13_SATA_PHY_2_TX_1P104V 426 |IOMUXC_GPR13_SATA_PHY_1_SLOW); 427 428 return 0; 429 } 430 #endif 431 432 #if defined(CONFIG_VIDEO_IPUV3) 433 434 static iomux_v3_cfg_t const backlight_pads[] = { 435 /* Backlight on RGB connector: J15 */ 436 MX6_PAD_SD1_DAT3__GPIO_1_21 | MUX_PAD_CTRL(NO_PAD_CTRL), 437 #define RGB_BACKLIGHT_GP IMX_GPIO_NR(1, 21) 438 439 /* Backlight on LVDS connector: J6 */ 440 MX6_PAD_SD1_CMD__GPIO_1_18 | MUX_PAD_CTRL(NO_PAD_CTRL), 441 #define LVDS_BACKLIGHT_GP IMX_GPIO_NR(1, 18) 442 }; 443 444 static iomux_v3_cfg_t const rgb_pads[] = { 445 MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, 446 MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15, 447 MX6_PAD_DI0_PIN2__IPU1_DI0_PIN2, 448 MX6_PAD_DI0_PIN3__IPU1_DI0_PIN3, 449 MX6_PAD_DI0_PIN4__GPIO_4_20, 450 MX6_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0, 451 MX6_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1, 452 MX6_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2, 453 MX6_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3, 454 MX6_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4, 455 MX6_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5, 456 MX6_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6, 457 MX6_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7, 458 MX6_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8, 459 MX6_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9, 460 MX6_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10, 461 MX6_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11, 462 MX6_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12, 463 MX6_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13, 464 MX6_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14, 465 MX6_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15, 466 MX6_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16, 467 MX6_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17, 468 MX6_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18, 469 MX6_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19, 470 MX6_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20, 471 MX6_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21, 472 MX6_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22, 473 MX6_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, 474 }; 475 476 struct display_info_t { 477 int bus; 478 int addr; 479 int pixfmt; 480 int (*detect)(struct display_info_t const *dev); 481 void (*enable)(struct display_info_t const *dev); 482 struct fb_videomode mode; 483 }; 484 485 486 static int detect_hdmi(struct display_info_t const *dev) 487 { 488 struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; 489 return readb(&hdmi->phy_stat0) & HDMI_PHY_HPD; 490 } 491 492 static void enable_hdmi(struct display_info_t const *dev) 493 { 494 struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; 495 u8 reg; 496 printf("%s: setup HDMI monitor\n", __func__); 497 reg = readb(&hdmi->phy_conf0); 498 reg |= HDMI_PHY_CONF0_PDZ_MASK; 499 writeb(reg, &hdmi->phy_conf0); 500 501 udelay(3000); 502 reg |= HDMI_PHY_CONF0_ENTMDS_MASK; 503 writeb(reg, &hdmi->phy_conf0); 504 udelay(3000); 505 reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK; 506 writeb(reg, &hdmi->phy_conf0); 507 writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz); 508 } 509 510 static int detect_i2c(struct display_info_t const *dev) 511 { 512 return ((0 == i2c_set_bus_num(dev->bus)) 513 && 514 (0 == i2c_probe(dev->addr))); 515 } 516 517 static void enable_lvds(struct display_info_t const *dev) 518 { 519 struct iomuxc *iomux = (struct iomuxc *) 520 IOMUXC_BASE_ADDR; 521 u32 reg = readl(&iomux->gpr[2]); 522 reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT; 523 writel(reg, &iomux->gpr[2]); 524 gpio_direction_output(LVDS_BACKLIGHT_GP, 1); 525 } 526 527 static void enable_rgb(struct display_info_t const *dev) 528 { 529 imx_iomux_v3_setup_multiple_pads( 530 rgb_pads, 531 ARRAY_SIZE(rgb_pads)); 532 gpio_direction_output(RGB_BACKLIGHT_GP, 1); 533 } 534 535 static struct display_info_t const displays[] = {{ 536 .bus = -1, 537 .addr = 0, 538 .pixfmt = IPU_PIX_FMT_RGB24, 539 .detect = detect_hdmi, 540 .enable = enable_hdmi, 541 .mode = { 542 .name = "HDMI", 543 .refresh = 60, 544 .xres = 1024, 545 .yres = 768, 546 .pixclock = 15385, 547 .left_margin = 220, 548 .right_margin = 40, 549 .upper_margin = 21, 550 .lower_margin = 7, 551 .hsync_len = 60, 552 .vsync_len = 10, 553 .sync = FB_SYNC_EXT, 554 .vmode = FB_VMODE_NONINTERLACED 555 } }, { 556 .bus = 2, 557 .addr = 0x4, 558 .pixfmt = IPU_PIX_FMT_LVDS666, 559 .detect = detect_i2c, 560 .enable = enable_lvds, 561 .mode = { 562 .name = "Hannstar-XGA", 563 .refresh = 60, 564 .xres = 1024, 565 .yres = 768, 566 .pixclock = 15385, 567 .left_margin = 220, 568 .right_margin = 40, 569 .upper_margin = 21, 570 .lower_margin = 7, 571 .hsync_len = 60, 572 .vsync_len = 10, 573 .sync = FB_SYNC_EXT, 574 .vmode = FB_VMODE_NONINTERLACED 575 } }, { 576 .bus = 2, 577 .addr = 0x38, 578 .pixfmt = IPU_PIX_FMT_LVDS666, 579 .detect = detect_i2c, 580 .enable = enable_lvds, 581 .mode = { 582 .name = "wsvga-lvds", 583 .refresh = 60, 584 .xres = 1024, 585 .yres = 600, 586 .pixclock = 15385, 587 .left_margin = 220, 588 .right_margin = 40, 589 .upper_margin = 21, 590 .lower_margin = 7, 591 .hsync_len = 60, 592 .vsync_len = 10, 593 .sync = FB_SYNC_EXT, 594 .vmode = FB_VMODE_NONINTERLACED 595 } }, { 596 .bus = 2, 597 .addr = 0x48, 598 .pixfmt = IPU_PIX_FMT_RGB666, 599 .detect = detect_i2c, 600 .enable = enable_rgb, 601 .mode = { 602 .name = "wvga-rgb", 603 .refresh = 57, 604 .xres = 800, 605 .yres = 480, 606 .pixclock = 37037, 607 .left_margin = 40, 608 .right_margin = 60, 609 .upper_margin = 10, 610 .lower_margin = 10, 611 .hsync_len = 20, 612 .vsync_len = 10, 613 .sync = 0, 614 .vmode = FB_VMODE_NONINTERLACED 615 } } }; 616 617 int board_video_skip(void) 618 { 619 int i; 620 int ret; 621 char const *panel = getenv("panel"); 622 if (!panel) { 623 for (i = 0; i < ARRAY_SIZE(displays); i++) { 624 struct display_info_t const *dev = displays+i; 625 if (dev->detect(dev)) { 626 panel = dev->mode.name; 627 printf("auto-detected panel %s\n", panel); 628 break; 629 } 630 } 631 if (!panel) { 632 panel = displays[0].mode.name; 633 printf("No panel detected: default to %s\n", panel); 634 } 635 } else { 636 for (i = 0; i < ARRAY_SIZE(displays); i++) { 637 if (!strcmp(panel, displays[i].mode.name)) 638 break; 639 } 640 } 641 if (i < ARRAY_SIZE(displays)) { 642 ret = ipuv3_fb_init(&displays[i].mode, 0, 643 displays[i].pixfmt); 644 if (!ret) { 645 displays[i].enable(displays+i); 646 printf("Display: %s (%ux%u)\n", 647 displays[i].mode.name, 648 displays[i].mode.xres, 649 displays[i].mode.yres); 650 } else 651 printf("LCD %s cannot be configured: %d\n", 652 displays[i].mode.name, ret); 653 } else { 654 printf("unsupported panel %s\n", panel); 655 ret = -EINVAL; 656 } 657 return (0 != ret); 658 } 659 660 static void setup_display(void) 661 { 662 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 663 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; 664 struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; 665 struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; 666 667 int reg; 668 669 /* Turn on LDB0,IPU,IPU DI0 clocks */ 670 reg = __raw_readl(&mxc_ccm->CCGR3); 671 reg |= MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET 672 |MXC_CCM_CCGR3_LDB_DI0_MASK; 673 writel(reg, &mxc_ccm->CCGR3); 674 675 /* Turn on HDMI PHY clock */ 676 reg = __raw_readl(&mxc_ccm->CCGR2); 677 reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK 678 |MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK; 679 writel(reg, &mxc_ccm->CCGR2); 680 681 /* clear HDMI PHY reset */ 682 writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz); 683 684 /* set PFD1_FRAC to 0x13 == 455 MHz (480*18)/0x13 */ 685 writel(ANATOP_PFD_480_PFD1_FRAC_MASK, &anatop->pfd_480_clr); 686 writel(0x13<<ANATOP_PFD_480_PFD1_FRAC_SHIFT, &anatop->pfd_480_set); 687 688 /* set LDB0, LDB1 clk select to 011/011 */ 689 reg = readl(&mxc_ccm->cs2cdr); 690 reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK 691 |MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK); 692 reg |= (3<<MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) 693 |(3<<MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET); 694 writel(reg, &mxc_ccm->cs2cdr); 695 696 reg = readl(&mxc_ccm->cscmr2); 697 reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV; 698 writel(reg, &mxc_ccm->cscmr2); 699 700 reg = readl(&mxc_ccm->chsccdr); 701 reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK 702 |MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK 703 |MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK); 704 reg |= (CHSCCDR_CLK_SEL_LDB_DI0 705 <<MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET) 706 |(CHSCCDR_PODF_DIVIDE_BY_3 707 <<MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) 708 |(CHSCCDR_IPU_PRE_CLK_540M_PFD 709 <<MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET); 710 writel(reg, &mxc_ccm->chsccdr); 711 712 reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES 713 |IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH 714 |IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW 715 |IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG 716 |IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT 717 |IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG 718 |IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT 719 |IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED 720 |IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0; 721 writel(reg, &iomux->gpr[2]); 722 723 reg = readl(&iomux->gpr[3]); 724 reg = (reg & ~IOMUXC_GPR3_LVDS0_MUX_CTL_MASK) 725 | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 726 <<IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET); 727 writel(reg, &iomux->gpr[3]); 728 729 /* backlights off until needed */ 730 imx_iomux_v3_setup_multiple_pads(backlight_pads, 731 ARRAY_SIZE(backlight_pads)); 732 gpio_direction_input(LVDS_BACKLIGHT_GP); 733 gpio_direction_input(RGB_BACKLIGHT_GP); 734 } 735 #endif 736 737 int board_early_init_f(void) 738 { 739 setup_iomux_uart(); 740 741 /* Disable wl1271 For Nitrogen6w */ 742 gpio_direction_input(WL12XX_WL_IRQ_GP); 743 gpio_direction_output(WL12XX_WL_ENABLE_GP, 0); 744 gpio_direction_output(WL12XX_BT_ENABLE_GP, 0); 745 746 imx_iomux_v3_setup_multiple_pads(wl12xx_pads, ARRAY_SIZE(wl12xx_pads)); 747 setup_buttons(); 748 749 #if defined(CONFIG_VIDEO_IPUV3) 750 setup_display(); 751 #endif 752 return 0; 753 } 754 755 /* 756 * Do not overwrite the console 757 * Use always serial for U-Boot console 758 */ 759 int overwrite_console(void) 760 { 761 return 1; 762 } 763 764 int board_init(void) 765 { 766 /* address of boot parameters */ 767 gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; 768 769 #ifdef CONFIG_MXC_SPI 770 setup_spi(); 771 #endif 772 setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0); 773 setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1); 774 setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2); 775 776 #ifdef CONFIG_CMD_SATA 777 setup_sata(); 778 #endif 779 780 return 0; 781 } 782 783 int checkboard(void) 784 { 785 if (gpio_get_value(WL12XX_WL_IRQ_GP)) 786 puts("Board: Nitrogen6X\n"); 787 else 788 puts("Board: SABRE Lite\n"); 789 790 return 0; 791 } 792 793 struct button_key { 794 char const *name; 795 unsigned gpnum; 796 char ident; 797 }; 798 799 static struct button_key const buttons[] = { 800 {"back", IMX_GPIO_NR(2, 2), 'B'}, 801 {"home", IMX_GPIO_NR(2, 4), 'H'}, 802 {"menu", IMX_GPIO_NR(2, 1), 'M'}, 803 {"search", IMX_GPIO_NR(2, 3), 'S'}, 804 {"volup", IMX_GPIO_NR(7, 13), 'V'}, 805 {"voldown", IMX_GPIO_NR(4, 5), 'v'}, 806 }; 807 808 /* 809 * generate a null-terminated string containing the buttons pressed 810 * returns number of keys pressed 811 */ 812 static int read_keys(char *buf) 813 { 814 int i, numpressed = 0; 815 for (i = 0; i < ARRAY_SIZE(buttons); i++) { 816 if (!gpio_get_value(buttons[i].gpnum)) 817 buf[numpressed++] = buttons[i].ident; 818 } 819 buf[numpressed] = '\0'; 820 return numpressed; 821 } 822 823 static int do_kbd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 824 { 825 char envvalue[ARRAY_SIZE(buttons)+1]; 826 int numpressed = read_keys(envvalue); 827 setenv("keybd", envvalue); 828 return numpressed == 0; 829 } 830 831 U_BOOT_CMD( 832 kbd, 1, 1, do_kbd, 833 "Tests for keypresses, sets 'keybd' environment variable", 834 "Returns 0 (true) to shell if key is pressed." 835 ); 836 837 #ifdef CONFIG_PREBOOT 838 static char const kbd_magic_prefix[] = "key_magic"; 839 static char const kbd_command_prefix[] = "key_cmd"; 840 841 static void preboot_keys(void) 842 { 843 int numpressed; 844 char keypress[ARRAY_SIZE(buttons)+1]; 845 numpressed = read_keys(keypress); 846 if (numpressed) { 847 char *kbd_magic_keys = getenv("magic_keys"); 848 char *suffix; 849 /* 850 * loop over all magic keys 851 */ 852 for (suffix = kbd_magic_keys; *suffix; ++suffix) { 853 char *keys; 854 char magic[sizeof(kbd_magic_prefix) + 1]; 855 sprintf(magic, "%s%c", kbd_magic_prefix, *suffix); 856 keys = getenv(magic); 857 if (keys) { 858 if (!strcmp(keys, keypress)) 859 break; 860 } 861 } 862 if (*suffix) { 863 char cmd_name[sizeof(kbd_command_prefix) + 1]; 864 char *cmd; 865 sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix); 866 cmd = getenv(cmd_name); 867 if (cmd) { 868 setenv("preboot", cmd); 869 return; 870 } 871 } 872 } 873 } 874 #endif 875 876 #ifdef CONFIG_CMD_BMODE 877 static const struct boot_mode board_boot_modes[] = { 878 /* 4 bit bus width */ 879 {"mmc0", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, 880 {"mmc1", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, 881 {NULL, 0}, 882 }; 883 #endif 884 885 int misc_init_r(void) 886 { 887 #ifdef CONFIG_PREBOOT 888 preboot_keys(); 889 #endif 890 891 #ifdef CONFIG_CMD_BMODE 892 add_board_boot_modes(board_boot_modes); 893 #endif 894 return 0; 895 } 896