u-boot-brain/board/udoo/udoo.c
Giuseppe Pagano db6801dec3 udoo: Fix watchdog during kernel boot.
uDoo uses APX823-31W5 watchdog chip. Timeout is about 1.2 seconds.
To disabled watchdog during kernel boot, WDI pin of that chip needs to be
in "high impedance" state. I.mx6 gpio configuration does not contemplate
tristate, so pin is set as input in high impedance.

Signed-off-by: Giuseppe Pagano <giuseppe.pagano@seco.com>
Reviewed-by: Fabio Estevam <fabio.estevam@freescale.com>
CC: Stefano Babic <sbabic@denx.de>
CC: Fabio Estevam <fabio.estevam@freescale.com>
2013-11-28 09:08:42 +01:00

252 lines
7.1 KiB
C

/*
* Copyright (C) 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/iomux.h>
#include <malloc.h>
#include <asm/arch/mx6-pins.h>
#include <asm/errno.h>
#include <asm/gpio.h>
#include <asm/imx-common/iomux-v3.h>
#include <mmc.h>
#include <fsl_esdhc.h>
#include <asm/arch/crm_regs.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <micrel.h>
#include <miiphy.h>
#include <netdev.h>
DECLARE_GLOBAL_DATA_PTR;
#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
PAD_CTL_SRE_FAST | PAD_CTL_HYS)
#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
PAD_CTL_SRE_FAST | PAD_CTL_HYS)
#define WDT_EN IMX_GPIO_NR(5, 4)
#define WDT_TRG IMX_GPIO_NR(3, 19)
int dram_init(void)
{
gd->ram_size = (phys_size_t)CONFIG_DDR_MB * 1024 * 1024;
return 0;
}
static iomux_v3_cfg_t const uart2_pads[] = {
MX6_PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
static iomux_v3_cfg_t const usdhc3_pads[] = {
MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};
static iomux_v3_cfg_t const wdog_pads[] = {
MX6_PAD_EIM_A24__GPIO5_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL),
MX6_PAD_EIM_D19__GPIO3_IO19,
};
int mx6_rgmii_rework(struct phy_device *phydev)
{
/*
* Bug: Apparently uDoo does not works with Gigabit switches...
* Limiting speed to 10/100Mbps, and setting master mode, seems to
* be the only way to have a successfull PHY auto negotiation.
* How to fix: Understand why Linux kernel do not have this issue.
*/
phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0x1c00);
/* control data pad skew - devaddr = 0x02, register = 0x04 */
ksz9031_phy_extended_write(phydev, 0x02,
MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW,
MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
/* rx data pad skew - devaddr = 0x02, register = 0x05 */
ksz9031_phy_extended_write(phydev, 0x02,
MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW,
MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
/* tx data pad skew - devaddr = 0x02, register = 0x05 */
ksz9031_phy_extended_write(phydev, 0x02,
MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW,
MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
/* gtx and rx clock pad skew - devaddr = 0x02, register = 0x08 */
ksz9031_phy_extended_write(phydev, 0x02,
MII_KSZ9031_EXT_RGMII_CLOCK_SKEW,
MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x03FF);
return 0;
}
static iomux_v3_cfg_t const enet_pads1[] = {
MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
/* RGMII reset */
MX6_PAD_EIM_D23__GPIO3_IO23 | MUX_PAD_CTRL(NO_PAD_CTRL),
/* Ethernet power supply */
MX6_PAD_EIM_EB3__GPIO2_IO31 | MUX_PAD_CTRL(NO_PAD_CTRL),
/* pin 32 - 1 - (MODE0) all */
MX6_PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL),
/* pin 31 - 1 - (MODE1) all */
MX6_PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL),
/* pin 28 - 1 - (MODE2) all */
MX6_PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL),
/* pin 27 - 1 - (MODE3) all */
MX6_PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
/* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
MX6_PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
static iomux_v3_cfg_t const enet_pads2[] = {
MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
};
static void setup_iomux_enet(void)
{
imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1));
udelay(20);
gpio_direction_output(IMX_GPIO_NR(2, 31), 1); /* Power supply on */
gpio_direction_output(IMX_GPIO_NR(3, 23), 0); /* assert PHY rst */
gpio_direction_output(IMX_GPIO_NR(6, 24), 1);
gpio_direction_output(IMX_GPIO_NR(6, 25), 1);
gpio_direction_output(IMX_GPIO_NR(6, 27), 1);
gpio_direction_output(IMX_GPIO_NR(6, 28), 1);
gpio_direction_output(IMX_GPIO_NR(6, 29), 1);
udelay(1000);
gpio_set_value(IMX_GPIO_NR(3, 23), 1); /* deassert PHY rst */
/* Need 100ms delay to exit from reset. */
udelay(1000 * 100);
gpio_free(IMX_GPIO_NR(6, 24));
gpio_free(IMX_GPIO_NR(6, 25));
gpio_free(IMX_GPIO_NR(6, 27));
gpio_free(IMX_GPIO_NR(6, 28));
gpio_free(IMX_GPIO_NR(6, 29));
imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2));
}
static void setup_iomux_uart(void)
{
imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
}
static void setup_iomux_wdog(void)
{
imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
gpio_direction_output(WDT_TRG, 0);
gpio_direction_output(WDT_EN, 1);
gpio_direction_input(WDT_TRG);
}
static struct fsl_esdhc_cfg usdhc_cfg = { USDHC3_BASE_ADDR };
int board_mmc_getcd(struct mmc *mmc)
{
return 1; /* Always present */
}
int board_eth_init(bd_t *bis)
{
uint32_t base = IMX_FEC_BASE;
struct mii_dev *bus = NULL;
struct phy_device *phydev = NULL;
int ret;
setup_iomux_enet();
#ifdef CONFIG_FEC_MXC
bus = fec_get_miibus(base, -1);
if (!bus)
return 0;
/* scan phy 4,5,6,7 */
phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII);
if (!phydev) {
free(bus);
return 0;
}
printf("using phy at %d\n", phydev->addr);
ret = fec_probe(bis, -1, base, bus, phydev);
if (ret) {
printf("FEC MXC: %s:failed\n", __func__);
free(phydev);
free(bus);
}
#endif
return 0;
}
int board_mmc_init(bd_t *bis)
{
imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
usdhc_cfg.max_bus_width = 4;
return fsl_esdhc_initialize(bis, &usdhc_cfg);
}
int board_early_init_f(void)
{
setup_iomux_wdog();
setup_iomux_uart();
return 0;
}
int board_phy_config(struct phy_device *phydev)
{
mx6_rgmii_rework(phydev);
if (phydev->drv->config)
phydev->drv->config(phydev);
return 0;
}
int board_init(void)
{
/* address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
return 0;
}
int checkboard(void)
{
puts("Board: Udoo\n");
return 0;
}