目录
1. 比对官方mx6ullevk开发板与ALIENTEK-ALPHA开发板原理图
1.1.下载NXP官方mx6ullevk原理图
NXP官方网站下载mx6ullevk原理图查看LCD显示屏硬件连接与ALIENTEK-ALPHA开发板LCD显示屏连接区别:
下载后进行解压,解压完成后如下图所示:
MCIMX6ULL_BB_DESIGNFILES:Baseboard底板,里面是外围芯片原理图
MCIMX6ULL_CM_DESIGNFILES:Core module核心板,里面是EMMC、DDR和PWR,如下图所示:
1.2. 比对NXP官方mx6ullevk开发板原理图与ALIENTEK-ALPHA开发板原理图差异
查看NXP官方mx6ullevk开发板网络PHY芯片与mx6ull芯片的硬件连接,打开MCIMX6ULL-EVK-DESIGNFILES\MCIMX6ULL_CM_DESIGNFILES\Schematic\SPF-29364_B1.pdf文件,找到网络PHY芯片的硬件连接,如下图所示:
然后在看下LCD显示屏的具体管脚,打开MCIMX6ULL-EVK-DESIGNFILES
MCIMX6ULL_BB_DESIGNFILES\Schematics\SCH-28616\spf-28616_e.pdf文件,找到网络芯片PHY原理图,如下图所示:
然后查看ALIENTEK-ALPHA V2.1(IMX6ULL_ALPHA_V2.1.pdf文件)底板网络芯片PHY原理图,如下如所示:
打开ALIENTEK-ALPHA核心板(IMX6ULL_CORE_V1.4.pdf文件)查看ENET1网络PHY芯片和ENET2网络PHY芯片与mx6ull芯片连接引脚,如下图所示:
对比官方mx6ullevk开发板与ALIENTEK-ALPHA开发板原理图可知,ALIENTEK-ALPHA开发板和官方mx6ullevk所使用的PHY芯片不同,NXP官方mx6ullevk使用PHY芯片为MICROCHIP公司KSZ8081RNB,ALIENTEK-ALPHAk开发板使用PHY芯片为SMSC公司LAN8720A。官方mx6ullevk开发板控制KSZ8081RNB芯片复位引脚是通过74LV595扩展而来,ALIENTEK-ALPHAk开发版ENET1网络LAN8720A复位引脚为SNVS_TAMPER7(GPIO5_IO07),ENET2网络LAN8720A复位引脚为SNVS_TAMPER8(GPIO5_IO08)。因此需要修改uboot中网络驱动适配ALIENTEK-ALPHAk开发版。
1.3. LAN8720A复位
查看LAN8720A芯片手册关于芯片复位操作。
由LAN8720A芯片手册可知,LAN8720A芯片有两种复位形式:硬件复位和软件复位。硬件复位要保持nRST引脚持续一段低电平且低电平的时间不能低于trstia(100uS);软件复位需要将Basic Control Register寄存器Soft Reset位置1;同时LAN8720要求同时进行硬件复位和软件复位操作。
2. 修改uboot中ENET网络驱动代码适配ALIENTEK-ALPHA开发板
2.1. 修改ENET网络PHY芯片地址
1.确定ENET网络PHY芯片地址
查看LAN8720A芯片手册关于芯片地址设置操作。
LAN8720A芯片有一个地址引脚(RXER/PHYAD0),通过配置这个引脚电平可以设置LAN8720A芯片地址,由上面ALIENTEK-ALPHA开发板原理图可知ENET1网络PHY芯片地址为0,ENET2网络PHY芯片地址为1。
2. 在mx6ull_alientek_emmc.h文件中修改PHY芯片地址,如下图所示:
2.2. 屏蔽uboot网络驱动代码74LV595相关代码
1. 打开mx6ull_alientek_emmc.c文件屏蔽74LV595芯片控制引脚,如下所示:
//屏蔽74LV595控制引脚
/*
#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),
};
*/
2. 打开mx6ull_alientek_emmc.c文件屏蔽74LV595芯片初始化及设置代码,如下所示:
/*
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);
};
*/
/*
void iox74lv_set(int index)
{
int i;
for (i = 7; i >= 0; i--) {
gpio_direction_output(IOX_SHCP, 0);
if (i == index)
gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]);
else
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);
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);
};
*/
3. 打开mx6ull_alientek_emmc.c文件屏蔽board_init()函数74LV595芯片控制引脚初始化代码,如下所示:
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_NAND_MXS
setup_gpmi_nand();
#endif
return 0;
}
2.3. 修改ENET1和ENET2网络PHY芯片复位控制引脚
1. 打开mx6ull_alientek_emmc.c文件定义ENET1和ENET2网络PHY芯片复位控制引脚
/*定义ENET1和ENET2网络PHY芯片复位控制引脚*/
#define ENET1_RESET IMX_GPIO_NR(5, 7) /*GPIO5_IO07*/
#define ENET2_RESET IMX_GPIO_NR(5, 8) /*GPIO5_IO08*/
2. 打开mx6ull_alientek_emmc.c文件找到ENET1和ENET2网络PHY芯片控制引脚数组,增加复位控制引脚
/*
* 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),
/*ENET1网络PHY芯片复位控制引脚*/
MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_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),
/*ENET2网络PHY芯片复位控制引脚*/
MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
3. 打开mx6ull_alientek_emmc.c文件找到ENET网络PHY控制引脚初始化函数,增加复位引脚初始化
static void setup_iomux_fec(int fec_id)
{
if (fec_id == 0)
{
imx_iomux_v3_setup_multiple_pads(fec1_pads,
ARRAY_SIZE(fec1_pads));
/*设置ENET1网络PHY芯片复位引脚,并复位PHY芯片*/
gpio_direction_output(ENET1_RESET,1);
gpio_set_value(ENET1_RESET,0);
mdelay(20);
gpio_set_value(ENET1_RESET,1);
}
else
{
imx_iomux_v3_setup_multiple_pads(fec2_pads,
ARRAY_SIZE(fec2_pads));
/*设置ENET2网络PHY芯片复位引脚,并复位PHY芯片*/
gpio_direction_output(ENET2_RESET,1);
gpio_set_value(ENET2_RESET,0);
mdelay(20);
gpio_set_value(ENET2_RESET,1);
}
}
2.4. 对LAN8720A芯片进行软件复位操作
前面我们提到LAN8720A芯片正常工作需要同时进行硬件复位和软件复位操作,硬件复位操作在mx6ull_alientek_emmc.c文件setup_iomux_fec()函数中已经完成软件复位操作需要在drivers/net/phy/phy.c文件中genphy_update_link()函数中实现。打开drivers/net
/phy/phy.c找到函数genphy_update_link,这个函数为PHY驱动函数,此函数用于更新PHY的连接状态和速度。在此函数中增加LAN8720A软件复位操作,修改后的genphy_update_link函数如下所示:
/**
* genphy_update_link - update link status in @phydev
* @phydev: target phy_device struct
*
* Description: Update the value in phydev->link to reflect the
* current link value. In order to do this, we need to read
* the status register twice, keeping the second value.
*/
int genphy_update_link(struct phy_device *phydev)
{
unsigned int mii_reg;
#ifdef CONFIG_PHY_SMSC
/*LAN8720A软件复位操作*/
static int lan8720_flag = 0;
int bmcr_reg = 0;
if (lan8720_flag == 0)
{
bmcr_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
while(phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR) & 0X8000)
{
udelay(100);
}
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr_reg);
lan8720_flag = 1;
}
#endif
/*
* Wait if the link is up, and autonegotiation is in progress
* (ie - we're capable and it's not done)
*/
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
..................
return 0;
}
2.5. 使能SMSC公司PHY驱动
打开mx6ull_alientek_emmc.h文件使能SMSC公司PHY驱动,修改后的代码如下所示:
#if (CONFIG_FEC_ENET_DEV == 0)
#define IMX_FEC_BASE ENET_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR 0x0
#define CONFIG_FEC_XCV_TYPE RMII
#elif (CONFIG_FEC_ENET_DEV == 1)
#define IMX_FEC_BASE ENET2_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR 0x1
#define CONFIG_FEC_XCV_TYPE RMII
#endif
#define CONFIG_ETHPRIME "FEC"
#define CONFIG_PHYLIB
//#define CONFIG_PHY_MICREL
/*使能SMSC公司PHY驱动*/
#define CONFIG_PHY_SMSC
#endif
3. 编译修改后的uboot源码
将修改后的uboot源码进行编译,执行结果如下图所示:
4. 烧写u-boot.bin测试网络通信
1. 将编译好的u-boot.bin文件使用imxdownload软件烧写到SD卡,进行测试,烧写文件如下图所示:
2. 将SD卡插入ALIENTEK-ALPHA开发板TF卡槽中,打开SecureCRT 软件,开发板上电,观察SecureCRT软件接收信息,如下图所示:
3. 查看Ubuntu主机IP地址,如下图所示:
4. 测试ENET2网络,设置uboot中环境变量,保证开发板和Ubuntu主机在同一个网段内,设置的环境变量如下图所示:
5. 使用ping命令测试网络连接,命令如下图所示:
6. 测试ENET1网路是否工作正常,打开mx6ull_alientek_emmc.h文件,将CONFIG_FEC_ENET_DEV宏定义修改为0,重新编译uboot将编译好的uboot烧录到SD卡中,操作如下图所示:
7. 将网线插入ENET1网络接口,插入SD卡,打开SecureCRT 软件,uboot输出信息如下图所示:
8. 使用ping命令测试网络连接,命令如下图所示:
由上图可知ENET1网络ping Ubuntu主机成功,说明ENET1网络工作正常,ALIENTEK-ALPHA开发板ENET1和ENET2网络测试完成。