@ -9,6 +9,7 @@
# 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>
@ -18,6 +19,9 @@
# 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 ;
@ -25,6 +29,9 @@ DECLARE_GLOBAL_DATA_PTR;
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 )
@ -58,6 +65,99 @@ static iomux_v3_cfg_t const wdog_pads[] = {
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 / 100 Mbps , 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 ) ) ;
@ -77,6 +177,37 @@ 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 ) ) ;
@ -94,6 +225,15 @@ int board_early_init_f(void)
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 */