mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-17 02:08:38 +00:00
0d7cdc2abf
The current pad DSE for QSPI is 60ohm. This setting cause too strong drive to clock and data signals. Need to change the DSE to 120ohm for better signal quality. Signed-off-by: Peng Fan <peng.fan@nxp.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Fabio Estevam <fabio.estevam@nxp.com> Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
875 lines
23 KiB
C
875 lines
23 KiB
C
/*
|
|
* Copyright (C) 2015 Freescale Semiconductor, Inc.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <asm/arch/clock.h>
|
|
#include <asm/arch/iomux.h>
|
|
#include <asm/arch/imx-regs.h>
|
|
#include <asm/arch/crm_regs.h>
|
|
#include <asm/arch/mx6ul_pins.h>
|
|
#include <asm/arch/mx6-pins.h>
|
|
#include <asm/arch/sys_proto.h>
|
|
#include <asm/gpio.h>
|
|
#include <asm/imx-common/iomux-v3.h>
|
|
#include <asm/imx-common/boot_mode.h>
|
|
#include <asm/imx-common/mxc_i2c.h>
|
|
#include <asm/io.h>
|
|
#include <common.h>
|
|
#include <fsl_esdhc.h>
|
|
#include <i2c.h>
|
|
#include <miiphy.h>
|
|
#include <linux/sizes.h>
|
|
#include <mmc.h>
|
|
#include <netdev.h>
|
|
#include <power/pmic.h>
|
|
#include <power/pfuze3000_pmic.h>
|
|
#include "../common/pfuze.h"
|
|
#include <usb.h>
|
|
#include <usb/ehci-ci.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
#define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
|
|
PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
|
|
PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
|
|
|
|
#define USDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
|
|
PAD_CTL_PUS_22K_UP | PAD_CTL_SPEED_LOW | \
|
|
PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
|
|
|
|
#define USDHC_DAT3_CD_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
|
|
PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_LOW | \
|
|
PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
|
|
|
|
#define I2C_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
|
|
PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
|
|
PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
|
|
PAD_CTL_ODE)
|
|
|
|
#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \
|
|
PAD_CTL_SPEED_HIGH | \
|
|
PAD_CTL_DSE_48ohm | PAD_CTL_SRE_FAST)
|
|
|
|
#define LCD_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \
|
|
PAD_CTL_PKE | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm)
|
|
|
|
#define MDIO_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \
|
|
PAD_CTL_DSE_48ohm | PAD_CTL_SRE_FAST | PAD_CTL_ODE)
|
|
|
|
#define ENET_CLK_PAD_CTRL (PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
|
|
|
|
#define ENET_RX_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
|
|
PAD_CTL_SPEED_HIGH | PAD_CTL_SRE_FAST)
|
|
|
|
#define IOX_SDI IMX_GPIO_NR(5, 10)
|
|
#define IOX_STCP IMX_GPIO_NR(5, 7)
|
|
#define IOX_SHCP IMX_GPIO_NR(5, 11)
|
|
#define IOX_OE IMX_GPIO_NR(5, 8)
|
|
|
|
static iomux_v3_cfg_t const iox_pads[] = {
|
|
/* IOX_SDI */
|
|
MX6_PAD_BOOT_MODE0__GPIO5_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
/* IOX_SHCP */
|
|
MX6_PAD_BOOT_MODE1__GPIO5_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
/* IOX_STCP */
|
|
MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
/* IOX_nOE */
|
|
MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
};
|
|
|
|
/*
|
|
* HDMI_nRST --> Q0
|
|
* ENET1_nRST --> Q1
|
|
* ENET2_nRST --> Q2
|
|
* CAN1_2_STBY --> Q3
|
|
* BT_nPWD --> Q4
|
|
* CSI_RST --> Q5
|
|
* CSI_PWDN --> Q6
|
|
* LCD_nPWREN --> Q7
|
|
*/
|
|
enum qn {
|
|
HDMI_NRST,
|
|
ENET1_NRST,
|
|
ENET2_NRST,
|
|
CAN1_2_STBY,
|
|
BT_NPWD,
|
|
CSI_RST,
|
|
CSI_PWDN,
|
|
LCD_NPWREN,
|
|
};
|
|
|
|
enum qn_func {
|
|
qn_reset,
|
|
qn_enable,
|
|
qn_disable,
|
|
};
|
|
|
|
enum qn_level {
|
|
qn_low = 0,
|
|
qn_high = 1,
|
|
};
|
|
|
|
static enum qn_level seq[3][2] = {
|
|
{0, 1}, {1, 1}, {0, 0}
|
|
};
|
|
|
|
static enum qn_func qn_output[8] = {
|
|
qn_reset, qn_reset, qn_reset, qn_enable, qn_disable, qn_reset,
|
|
qn_disable, qn_disable
|
|
};
|
|
|
|
static void iox74lv_init(void)
|
|
{
|
|
int i;
|
|
|
|
gpio_direction_output(IOX_OE, 0);
|
|
|
|
for (i = 7; i >= 0; i--) {
|
|
gpio_direction_output(IOX_SHCP, 0);
|
|
gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]);
|
|
udelay(500);
|
|
gpio_direction_output(IOX_SHCP, 1);
|
|
udelay(500);
|
|
}
|
|
|
|
gpio_direction_output(IOX_STCP, 0);
|
|
udelay(500);
|
|
/*
|
|
* shift register will be output to pins
|
|
*/
|
|
gpio_direction_output(IOX_STCP, 1);
|
|
|
|
for (i = 7; i >= 0; i--) {
|
|
gpio_direction_output(IOX_SHCP, 0);
|
|
gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]);
|
|
udelay(500);
|
|
gpio_direction_output(IOX_SHCP, 1);
|
|
udelay(500);
|
|
}
|
|
gpio_direction_output(IOX_STCP, 0);
|
|
udelay(500);
|
|
/*
|
|
* shift register will be output to pins
|
|
*/
|
|
gpio_direction_output(IOX_STCP, 1);
|
|
};
|
|
|
|
#ifdef CONFIG_SYS_I2C_MXC
|
|
#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
|
|
/* I2C1 for PMIC and EEPROM */
|
|
static struct i2c_pads_info i2c_pad_info1 = {
|
|
.scl = {
|
|
.i2c_mode = MX6_PAD_UART4_TX_DATA__I2C1_SCL | PC,
|
|
.gpio_mode = MX6_PAD_UART4_TX_DATA__GPIO1_IO28 | PC,
|
|
.gp = IMX_GPIO_NR(1, 28),
|
|
},
|
|
.sda = {
|
|
.i2c_mode = MX6_PAD_UART4_RX_DATA__I2C1_SDA | PC,
|
|
.gpio_mode = MX6_PAD_UART4_RX_DATA__GPIO1_IO29 | PC,
|
|
.gp = IMX_GPIO_NR(1, 29),
|
|
},
|
|
};
|
|
|
|
#ifdef CONFIG_POWER
|
|
#define I2C_PMIC 0
|
|
int power_init_board(void)
|
|
{
|
|
if (is_mx6ul_9x9_evk()) {
|
|
struct pmic *pfuze;
|
|
int ret;
|
|
unsigned int reg, rev_id;
|
|
|
|
ret = power_pfuze3000_init(I2C_PMIC);
|
|
if (ret)
|
|
return ret;
|
|
|
|
pfuze = pmic_get("PFUZE3000");
|
|
ret = pmic_probe(pfuze);
|
|
if (ret)
|
|
return ret;
|
|
|
|
pmic_reg_read(pfuze, PFUZE3000_DEVICEID, ®);
|
|
pmic_reg_read(pfuze, PFUZE3000_REVID, &rev_id);
|
|
printf("PMIC: PFUZE3000 DEV_ID=0x%x REV_ID=0x%x\n",
|
|
reg, rev_id);
|
|
|
|
/* disable Low Power Mode during standby mode */
|
|
pmic_reg_read(pfuze, PFUZE3000_LDOGCTL, ®);
|
|
reg |= 0x1;
|
|
pmic_reg_write(pfuze, PFUZE3000_LDOGCTL, reg);
|
|
|
|
/* SW1B step ramp up time from 2us to 4us/25mV */
|
|
reg = 0x40;
|
|
pmic_reg_write(pfuze, PFUZE3000_SW1BCONF, reg);
|
|
|
|
/* SW1B mode to APS/PFM */
|
|
reg = 0xc;
|
|
pmic_reg_write(pfuze, PFUZE3000_SW1BMODE, reg);
|
|
|
|
/* SW1B standby voltage set to 0.975V */
|
|
reg = 0xb;
|
|
pmic_reg_write(pfuze, PFUZE3000_SW1BSTBY, reg);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
int dram_init(void)
|
|
{
|
|
gd->ram_size = imx_ddr_size();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static iomux_v3_cfg_t const uart1_pads[] = {
|
|
MX6_PAD_UART1_TX_DATA__UART1_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
|
MX6_PAD_UART1_RX_DATA__UART1_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
|
};
|
|
|
|
static iomux_v3_cfg_t const usdhc1_pads[] = {
|
|
MX6_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
|
|
/* VSELECT */
|
|
MX6_PAD_GPIO1_IO05__USDHC1_VSELECT | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
/* CD */
|
|
MX6_PAD_UART1_RTS_B__GPIO1_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
/* RST_B */
|
|
MX6_PAD_GPIO1_IO09__GPIO1_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
};
|
|
|
|
/*
|
|
* mx6ul_14x14_evk board default supports sd card. If want to use
|
|
* EMMC, need to do board rework for sd2.
|
|
* Introduce CONFIG_MX6UL_14X14_EVK_EMMC_REWORK, if sd2 reworked to support
|
|
* emmc, need to define this macro.
|
|
*/
|
|
#if defined(CONFIG_MX6UL_14X14_EVK_EMMC_REWORK)
|
|
static iomux_v3_cfg_t const usdhc2_emmc_pads[] = {
|
|
MX6_PAD_NAND_RE_B__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_WE_B__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA00__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA01__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA02__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA03__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA04__USDHC2_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA05__USDHC2_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA06__USDHC2_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA07__USDHC2_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
|
|
/*
|
|
* RST_B
|
|
*/
|
|
MX6_PAD_NAND_ALE__GPIO4_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
};
|
|
#else
|
|
static iomux_v3_cfg_t const usdhc2_pads[] = {
|
|
MX6_PAD_NAND_RE_B__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_WE_B__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA00__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA01__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA02__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
MX6_PAD_NAND_DATA03__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
|
};
|
|
|
|
static iomux_v3_cfg_t const usdhc2_cd_pads[] = {
|
|
/*
|
|
* The evk board uses DAT3 to detect CD card plugin,
|
|
* in u-boot we mux the pin to GPIO when doing board_mmc_getcd.
|
|
*/
|
|
MX6_PAD_NAND_DATA03__GPIO4_IO05 | MUX_PAD_CTRL(USDHC_DAT3_CD_PAD_CTRL),
|
|
};
|
|
|
|
static iomux_v3_cfg_t const usdhc2_dat3_pads[] = {
|
|
MX6_PAD_NAND_DATA03__USDHC2_DATA3 |
|
|
MUX_PAD_CTRL(USDHC_DAT3_CD_PAD_CTRL),
|
|
};
|
|
#endif
|
|
|
|
static void setup_iomux_uart(void)
|
|
{
|
|
imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
|
|
}
|
|
|
|
#ifdef CONFIG_FSL_QSPI
|
|
|
|
#define QSPI_PAD_CTRL1 \
|
|
(PAD_CTL_SRE_FAST | PAD_CTL_SPEED_MED | \
|
|
PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_120ohm)
|
|
|
|
static iomux_v3_cfg_t const quadspi_pads[] = {
|
|
MX6_PAD_NAND_WP_B__QSPI_A_SCLK | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
|
|
MX6_PAD_NAND_READY_B__QSPI_A_DATA00 | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
|
|
MX6_PAD_NAND_CE0_B__QSPI_A_DATA01 | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
|
|
MX6_PAD_NAND_CE1_B__QSPI_A_DATA02 | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
|
|
MX6_PAD_NAND_CLE__QSPI_A_DATA03 | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
|
|
MX6_PAD_NAND_DQS__QSPI_A_SS0_B | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
|
|
};
|
|
|
|
static int board_qspi_init(void)
|
|
{
|
|
/* Set the iomux */
|
|
imx_iomux_v3_setup_multiple_pads(quadspi_pads,
|
|
ARRAY_SIZE(quadspi_pads));
|
|
/* Set the clock */
|
|
enable_qspi_clk(0);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_FSL_ESDHC
|
|
static struct fsl_esdhc_cfg usdhc_cfg[2] = {
|
|
{USDHC1_BASE_ADDR, 0, 4},
|
|
#if defined(CONFIG_MX6UL_14X14_EVK_EMMC_REWORK)
|
|
{USDHC2_BASE_ADDR, 0, 8},
|
|
#else
|
|
{USDHC2_BASE_ADDR, 0, 4},
|
|
#endif
|
|
};
|
|
|
|
#define USDHC1_CD_GPIO IMX_GPIO_NR(1, 19)
|
|
#define USDHC1_PWR_GPIO IMX_GPIO_NR(1, 9)
|
|
#define USDHC2_CD_GPIO IMX_GPIO_NR(4, 5)
|
|
#define USDHC2_PWR_GPIO IMX_GPIO_NR(4, 10)
|
|
|
|
int board_mmc_getcd(struct mmc *mmc)
|
|
{
|
|
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
|
int ret = 0;
|
|
|
|
switch (cfg->esdhc_base) {
|
|
case USDHC1_BASE_ADDR:
|
|
ret = !gpio_get_value(USDHC1_CD_GPIO);
|
|
break;
|
|
case USDHC2_BASE_ADDR:
|
|
#if defined(CONFIG_MX6UL_14X14_EVK_EMMC_REWORK)
|
|
ret = 1;
|
|
#else
|
|
imx_iomux_v3_setup_multiple_pads(usdhc2_cd_pads,
|
|
ARRAY_SIZE(usdhc2_cd_pads));
|
|
gpio_direction_input(USDHC2_CD_GPIO);
|
|
|
|
/*
|
|
* Since it is the DAT3 pin, this pin is pulled to
|
|
* low voltage if no card
|
|
*/
|
|
ret = gpio_get_value(USDHC2_CD_GPIO);
|
|
|
|
imx_iomux_v3_setup_multiple_pads(usdhc2_dat3_pads,
|
|
ARRAY_SIZE(usdhc2_dat3_pads));
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int board_mmc_init(bd_t *bis)
|
|
{
|
|
#ifdef CONFIG_SPL_BUILD
|
|
#if defined(CONFIG_MX6UL_14X14_EVK_EMMC_REWORK)
|
|
imx_iomux_v3_setup_multiple_pads(usdhc2_emmc_pads,
|
|
ARRAY_SIZE(usdhc2_emmc_pads));
|
|
#else
|
|
imx_iomux_v3_setup_multiple_pads(usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
|
|
#endif
|
|
gpio_direction_output(USDHC2_PWR_GPIO, 0);
|
|
udelay(500);
|
|
gpio_direction_output(USDHC2_PWR_GPIO, 1);
|
|
usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
|
|
return fsl_esdhc_initialize(bis, &usdhc_cfg[1]);
|
|
#else
|
|
int i, ret;
|
|
|
|
/*
|
|
* According to the board_mmc_init() the following map is done:
|
|
* (U-Boot device node) (Physical Port)
|
|
* mmc0 USDHC1
|
|
* mmc1 USDHC2
|
|
*/
|
|
for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
|
|
switch (i) {
|
|
case 0:
|
|
imx_iomux_v3_setup_multiple_pads(
|
|
usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
|
|
gpio_direction_input(USDHC1_CD_GPIO);
|
|
usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
|
|
|
|
gpio_direction_output(USDHC1_PWR_GPIO, 0);
|
|
udelay(500);
|
|
gpio_direction_output(USDHC1_PWR_GPIO, 1);
|
|
break;
|
|
case 1:
|
|
#if defined(CONFIG_MX6UL_14X14_EVK_EMMC_REWORK)
|
|
imx_iomux_v3_setup_multiple_pads(
|
|
usdhc2_emmc_pads, ARRAY_SIZE(usdhc2_emmc_pads));
|
|
#else
|
|
imx_iomux_v3_setup_multiple_pads(
|
|
usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
|
|
#endif
|
|
gpio_direction_output(USDHC2_PWR_GPIO, 0);
|
|
udelay(500);
|
|
gpio_direction_output(USDHC2_PWR_GPIO, 1);
|
|
usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
|
|
break;
|
|
default:
|
|
printf("Warning: you configured more USDHC controllers (%d) than supported by the board\n", i + 1);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
|
|
if (ret) {
|
|
printf("Warning: failed to initialize mmc dev %d\n", i);
|
|
return ret;
|
|
}
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_EHCI_MX6
|
|
#define USB_OTHERREGS_OFFSET 0x800
|
|
#define UCTRL_PWR_POL (1 << 9)
|
|
|
|
static iomux_v3_cfg_t const usb_otg_pads[] = {
|
|
MX6_PAD_GPIO1_IO00__ANATOP_OTG1_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
};
|
|
|
|
/* At default the 3v3 enables the MIC2026 for VBUS power */
|
|
static void setup_usb(void)
|
|
{
|
|
imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
|
|
ARRAY_SIZE(usb_otg_pads));
|
|
}
|
|
|
|
int board_usb_phy_mode(int port)
|
|
{
|
|
if (port == 1)
|
|
return USB_INIT_HOST;
|
|
else
|
|
return usb_phy_mode(port);
|
|
}
|
|
|
|
int board_ehci_hcd_init(int port)
|
|
{
|
|
u32 *usbnc_usb_ctrl;
|
|
|
|
if (port > 1)
|
|
return -EINVAL;
|
|
|
|
usbnc_usb_ctrl = (u32 *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET +
|
|
port * 4);
|
|
|
|
/* Set Power polarity */
|
|
setbits_le32(usbnc_usb_ctrl, UCTRL_PWR_POL);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_FEC_MXC
|
|
/*
|
|
* pin conflicts for fec1 and fec2, GPIO1_IO06 and GPIO1_IO07 can only
|
|
* be used for ENET1 or ENET2, cannot be used for both.
|
|
*/
|
|
static iomux_v3_cfg_t const fec1_pads[] = {
|
|
MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
|
|
MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET1_TX_DATA0__ENET1_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET1_TX_DATA1__ENET1_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET1_TX_EN__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
|
|
MX6_PAD_ENET1_RX_DATA0__ENET1_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET1_RX_DATA1__ENET1_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
};
|
|
|
|
static iomux_v3_cfg_t const fec2_pads[] = {
|
|
MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
|
|
MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
|
|
MX6_PAD_ENET2_TX_DATA0__ENET2_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET2_TX_DATA1__ENET2_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
|
|
MX6_PAD_ENET2_TX_EN__ENET2_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
|
|
MX6_PAD_ENET2_RX_DATA0__ENET2_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET2_RX_DATA1__ENET2_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
|
|
};
|
|
|
|
static void setup_iomux_fec(int fec_id)
|
|
{
|
|
if (fec_id == 0)
|
|
imx_iomux_v3_setup_multiple_pads(fec1_pads,
|
|
ARRAY_SIZE(fec1_pads));
|
|
else
|
|
imx_iomux_v3_setup_multiple_pads(fec2_pads,
|
|
ARRAY_SIZE(fec2_pads));
|
|
}
|
|
|
|
int board_eth_init(bd_t *bis)
|
|
{
|
|
setup_iomux_fec(CONFIG_FEC_ENET_DEV);
|
|
|
|
return fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV,
|
|
CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
|
|
}
|
|
|
|
static int setup_fec(int fec_id)
|
|
{
|
|
struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
|
|
int ret;
|
|
|
|
if (fec_id == 0) {
|
|
/*
|
|
* Use 50M anatop loopback REF_CLK1 for ENET1,
|
|
* clear gpr1[13], set gpr1[17].
|
|
*/
|
|
clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK,
|
|
IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK);
|
|
} else {
|
|
/*
|
|
* Use 50M anatop loopback REF_CLK2 for ENET2,
|
|
* clear gpr1[14], set gpr1[18].
|
|
*/
|
|
clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC2_MASK,
|
|
IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
|
|
}
|
|
|
|
ret = enable_fec_anatop_clock(fec_id, ENET_50MHZ);
|
|
if (ret)
|
|
return ret;
|
|
|
|
enable_enet_clk(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int board_phy_config(struct phy_device *phydev)
|
|
{
|
|
phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x8190);
|
|
|
|
if (phydev->drv->config)
|
|
phydev->drv->config(phydev);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_VIDEO_MXS
|
|
static iomux_v3_cfg_t const lcd_pads[] = {
|
|
MX6_PAD_LCD_CLK__LCDIF_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_ENABLE__LCDIF_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_HSYNC__LCDIF_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_VSYNC__LCDIF_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA00__LCDIF_DATA00 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA01__LCDIF_DATA01 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA02__LCDIF_DATA02 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA03__LCDIF_DATA03 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA04__LCDIF_DATA04 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA05__LCDIF_DATA05 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA06__LCDIF_DATA06 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA07__LCDIF_DATA07 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA08__LCDIF_DATA08 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA09__LCDIF_DATA09 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA10__LCDIF_DATA10 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA11__LCDIF_DATA11 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA12__LCDIF_DATA12 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA13__LCDIF_DATA13 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA14__LCDIF_DATA14 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA15__LCDIF_DATA15 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA16__LCDIF_DATA16 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA17__LCDIF_DATA17 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA18__LCDIF_DATA18 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA19__LCDIF_DATA19 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA20__LCDIF_DATA20 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA21__LCDIF_DATA21 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA22__LCDIF_DATA22 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
MX6_PAD_LCD_DATA23__LCDIF_DATA23 | MUX_PAD_CTRL(LCD_PAD_CTRL),
|
|
|
|
/* LCD_RST */
|
|
MX6_PAD_SNVS_TAMPER9__GPIO5_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
|
|
/* Use GPIO for Brightness adjustment, duty cycle = period. */
|
|
MX6_PAD_GPIO1_IO08__GPIO1_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
|
};
|
|
|
|
static int setup_lcd(void)
|
|
{
|
|
enable_lcdif_clock(LCDIF1_BASE_ADDR);
|
|
|
|
imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
|
|
|
|
/* Reset the LCD */
|
|
gpio_direction_output(IMX_GPIO_NR(5, 9) , 0);
|
|
udelay(500);
|
|
gpio_direction_output(IMX_GPIO_NR(5, 9) , 1);
|
|
|
|
/* Set Brightness to high */
|
|
gpio_direction_output(IMX_GPIO_NR(1, 8) , 1);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int board_early_init_f(void)
|
|
{
|
|
setup_iomux_uart();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int board_init(void)
|
|
{
|
|
/* Address of boot parameters */
|
|
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
|
|
|
|
imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));
|
|
|
|
iox74lv_init();
|
|
|
|
#ifdef CONFIG_SYS_I2C_MXC
|
|
setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
|
|
#endif
|
|
|
|
#ifdef CONFIG_FEC_MXC
|
|
setup_fec(CONFIG_FEC_ENET_DEV);
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_EHCI_MX6
|
|
setup_usb();
|
|
#endif
|
|
|
|
#ifdef CONFIG_FSL_QSPI
|
|
board_qspi_init();
|
|
#endif
|
|
|
|
#ifdef CONFIG_VIDEO_MXS
|
|
setup_lcd();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_CMD_BMODE
|
|
static const struct boot_mode board_boot_modes[] = {
|
|
/* 4 bit bus width */
|
|
{"sd1", MAKE_CFGVAL(0x42, 0x20, 0x00, 0x00)},
|
|
{"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
|
|
{"qspi1", MAKE_CFGVAL(0x10, 0x00, 0x00, 0x00)},
|
|
{NULL, 0},
|
|
};
|
|
#endif
|
|
|
|
int board_late_init(void)
|
|
{
|
|
#ifdef CONFIG_CMD_BMODE
|
|
add_board_boot_modes(board_boot_modes);
|
|
#endif
|
|
|
|
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
|
|
setenv("board_name", "EVK");
|
|
|
|
if (is_mx6ul_9x9_evk())
|
|
setenv("board_rev", "9X9");
|
|
else
|
|
setenv("board_rev", "14X14");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
int checkboard(void)
|
|
{
|
|
if (is_mx6ul_9x9_evk())
|
|
puts("Board: MX6UL 9x9 EVK\n");
|
|
else
|
|
puts("Board: MX6UL 14x14 EVK\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_SPL_BUILD
|
|
#include <libfdt.h>
|
|
#include <spl.h>
|
|
#include <asm/arch/mx6-ddr.h>
|
|
|
|
|
|
static struct mx6ul_iomux_grp_regs mx6_grp_ioregs = {
|
|
.grp_addds = 0x00000030,
|
|
.grp_ddrmode_ctl = 0x00020000,
|
|
.grp_b0ds = 0x00000030,
|
|
.grp_ctlds = 0x00000030,
|
|
.grp_b1ds = 0x00000030,
|
|
.grp_ddrpke = 0x00000000,
|
|
.grp_ddrmode = 0x00020000,
|
|
#ifdef CONFIG_TARGET_MX6UL_9X9_EVK
|
|
.grp_ddr_type = 0x00080000,
|
|
#else
|
|
.grp_ddr_type = 0x000c0000,
|
|
#endif
|
|
};
|
|
|
|
#ifdef CONFIG_TARGET_MX6UL_9X9_EVK
|
|
static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = {
|
|
.dram_dqm0 = 0x00000030,
|
|
.dram_dqm1 = 0x00000030,
|
|
.dram_ras = 0x00000030,
|
|
.dram_cas = 0x00000030,
|
|
.dram_odt0 = 0x00000000,
|
|
.dram_odt1 = 0x00000000,
|
|
.dram_sdba2 = 0x00000000,
|
|
.dram_sdclk_0 = 0x00000030,
|
|
.dram_sdqs0 = 0x00003030,
|
|
.dram_sdqs1 = 0x00003030,
|
|
.dram_reset = 0x00000030,
|
|
};
|
|
|
|
static struct mx6_mmdc_calibration mx6_mmcd_calib = {
|
|
.p0_mpwldectrl0 = 0x00000000,
|
|
.p0_mpdgctrl0 = 0x20000000,
|
|
.p0_mprddlctl = 0x4040484f,
|
|
.p0_mpwrdlctl = 0x40405247,
|
|
.mpzqlp2ctl = 0x1b4700c7,
|
|
};
|
|
|
|
static struct mx6_lpddr2_cfg mem_ddr = {
|
|
.mem_speed = 800,
|
|
.density = 2,
|
|
.width = 16,
|
|
.banks = 4,
|
|
.rowaddr = 14,
|
|
.coladdr = 10,
|
|
.trcd_lp = 1500,
|
|
.trppb_lp = 1500,
|
|
.trpab_lp = 2000,
|
|
.trasmin = 4250,
|
|
};
|
|
|
|
struct mx6_ddr_sysinfo ddr_sysinfo = {
|
|
.dsize = 0,
|
|
.cs_density = 18,
|
|
.ncs = 1,
|
|
.cs1_mirror = 0,
|
|
.walat = 0,
|
|
.ralat = 5,
|
|
.mif3_mode = 3,
|
|
.bi_on = 1,
|
|
.rtt_wr = 0, /* LPDDR2 does not need rtt_wr rtt_nom */
|
|
.rtt_nom = 0,
|
|
.sde_to_rst = 0, /* LPDDR2 does not need this field */
|
|
.rst_to_cke = 0x10, /* JEDEC value for LPDDR2: 200us */
|
|
.ddr_type = DDR_TYPE_LPDDR2,
|
|
};
|
|
|
|
#else
|
|
static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = {
|
|
.dram_dqm0 = 0x00000030,
|
|
.dram_dqm1 = 0x00000030,
|
|
.dram_ras = 0x00000030,
|
|
.dram_cas = 0x00000030,
|
|
.dram_odt0 = 0x00000030,
|
|
.dram_odt1 = 0x00000030,
|
|
.dram_sdba2 = 0x00000000,
|
|
.dram_sdclk_0 = 0x00000008,
|
|
.dram_sdqs0 = 0x00000038,
|
|
.dram_sdqs1 = 0x00000030,
|
|
.dram_reset = 0x00000030,
|
|
};
|
|
|
|
static struct mx6_mmdc_calibration mx6_mmcd_calib = {
|
|
.p0_mpwldectrl0 = 0x00070007,
|
|
.p0_mpdgctrl0 = 0x41490145,
|
|
.p0_mprddlctl = 0x40404546,
|
|
.p0_mpwrdlctl = 0x4040524D,
|
|
};
|
|
|
|
struct mx6_ddr_sysinfo ddr_sysinfo = {
|
|
.dsize = 0,
|
|
.cs_density = 20,
|
|
.ncs = 1,
|
|
.cs1_mirror = 0,
|
|
.rtt_wr = 2,
|
|
.rtt_nom = 1, /* RTT_Nom = RZQ/2 */
|
|
.walat = 1, /* Write additional latency */
|
|
.ralat = 5, /* Read additional latency */
|
|
.mif3_mode = 3, /* Command prediction working mode */
|
|
.bi_on = 1, /* Bank interleaving enabled */
|
|
.sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
|
|
.rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
|
|
.ddr_type = DDR_TYPE_DDR3,
|
|
};
|
|
|
|
static struct mx6_ddr3_cfg mem_ddr = {
|
|
.mem_speed = 800,
|
|
.density = 4,
|
|
.width = 16,
|
|
.banks = 8,
|
|
.rowaddr = 15,
|
|
.coladdr = 10,
|
|
.pagesz = 2,
|
|
.trcd = 1375,
|
|
.trcmin = 4875,
|
|
.trasmin = 3500,
|
|
};
|
|
#endif
|
|
|
|
static void ccgr_init(void)
|
|
{
|
|
struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
|
|
|
|
writel(0xFFFFFFFF, &ccm->CCGR0);
|
|
writel(0xFFFFFFFF, &ccm->CCGR1);
|
|
writel(0xFFFFFFFF, &ccm->CCGR2);
|
|
writel(0xFFFFFFFF, &ccm->CCGR3);
|
|
writel(0xFFFFFFFF, &ccm->CCGR4);
|
|
writel(0xFFFFFFFF, &ccm->CCGR5);
|
|
writel(0xFFFFFFFF, &ccm->CCGR6);
|
|
writel(0xFFFFFFFF, &ccm->CCGR7);
|
|
}
|
|
|
|
static void spl_dram_init(void)
|
|
{
|
|
mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
|
|
mx6_dram_cfg(&ddr_sysinfo, &mx6_mmcd_calib, &mem_ddr);
|
|
}
|
|
|
|
void board_init_f(ulong dummy)
|
|
{
|
|
/* setup AIPS and disable watchdog */
|
|
arch_cpu_init();
|
|
|
|
ccgr_init();
|
|
|
|
/* iomux and setup of i2c */
|
|
board_early_init_f();
|
|
|
|
/* setup GP timer */
|
|
timer_init();
|
|
|
|
/* UART clocks enabled and gd valid - init serial console */
|
|
preloader_console_init();
|
|
|
|
/* DDR initialization */
|
|
spl_dram_init();
|
|
|
|
/* Clear the BSS. */
|
|
memset(__bss_start, 0, __bss_end - __bss_start);
|
|
|
|
/* load/boot image from boot device */
|
|
board_init_r(NULL, 0);
|
|
}
|
|
#endif
|