U-Boot移植(在I.MX6ULL ALPHA开发板上移植)

U-Boot 在IMX6ULL上的移植(2)
1. LCD(4.3寸,分辨率800x480)参数的修改
由于我使用的I.MX6ULL ALPHA开发板LCD原理图与NXP的一致,所以LCD的IO部分就不用修改了。需要修改的LCD参数在mx6ull_alientek_emmc.c文件中,在文件中找到名为struct display_info_t const display[] 的结构体。该结构体保存着LCD的名称变量,长、宽变量以及时间参数等等。在这个结构体中有一项参数:pixclock 像素时钟需要根据自己的LCD屏幕时间参数进行计算,计算公式如下:
pxclk = {[(VSPW+VBP+LINE+VFP) * (HSPW+HBP+HOZVAL+HFP)] * 60} **** (1)
以上参数都在LCD数据手册能找到。
pixclock = (1 / pxclk) * 10^12 ***************************************************** (2)
由1,2式即可计算出pixclock的值。
U-Boot移植(在I.MX6ULL ALPHA开发板上移植)_第1张图片
再打开mx6ull_alientek_emmc.h文件找到panel=TFTAB,改为:panel=ATK4384,这个名字随意。但是要与U-Boot环境变量中的panel的值一致,连接开发板,打开secureCRT,启动开发板进入U-Boot之后,输入printenv,查看panel环境变量的值是否为ATK4384,如果不是,使用如下指令修改:

setenv panel ATK4384
saveenv

只有保持一致,LCD屏幕才会显示NXP的LOGO以及U-Boot的编译时间

2. 网络驱动的修改
在这里使用的网卡是LAN8720A芯片,IMX6ULL ALPHA开发板的网卡引脚除了复位脚和NXP的不一样,其他引脚都一样,此外NXP使用的网络芯片是KSZ8081芯片,所以在源码中要删除KSZ80801的相关代码,并编写LAN8720A的相关代码。在mx6ull_alientek_emmc.c中找到如下代码删除并改成:

#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)
//修改为
#define ENET1_RESET			IMX_GPIO_NR(5, 7)
#define ENET2_RESET			IMX_GPIO_NR(5, 8 ).

NXP使用74LV595来扩展IO,以上删除都是74LV595的驱动代码,继续找到如下代码删除:

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), 

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); 
    }
    ...... 
    /* 
     * 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); 
    } 
    ...... 
    /* 
      * shift register will be output to pins 
      */ 
    gpio_direction_output(IOX_STCP, 1); 
};

再找到如下代码:

int board_init(void) 
{ 
	...... 
	imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads)); 
    iox74lv_init(); 
    ......                                                                                    

    return 0; 
} 

删除其中的两个74lv595的初始化和配置代码。
继续找到如下代码:

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_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_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), 
 };

分别在两个结构最后一行添加如下两行代码:

MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),

这是添加开发板ENET1和ENET2两个网口的复位IO配置参数。
继续找到setup_iomux_fec()函数,将函数内容修改为:

static void setup_iomux_fec(int fec_id)
{
	if (fec_id == 0) {
		imx_iomux_v3_setup_multiple_pads(fec1_pads,
						ARRAY_SIZE(fec1_pads));
		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));
		gpio_direction_output(ENET2_RESET, 1);
		gpio_set_value(ENET2_RESET, 0);
		mdelay(20);
		gpio_set_value(ENET2_RESET, 1);
	}
}

函数 setup_iomux_fec 就是根据 fec1_pads 和 fec2_pads 这两个网络 IO 配置数组来初始化
I.MX6ULL 的网络 IO。我们需要在其中添加网络复位 IO 的初始化代码,并且复位一下 PHY 芯
片。

修改 drivers/net/phy/phy.c 文件中的函数 genphy_update_link,打开文件drivers/net/phy/phy.c,找到函数 genphy_update_link,这是个通用 PHY 驱动函数,此函数用于更新 PHY 的连接状态和速度。使用 LAN8720A 的时候需要在此函数中添加一些代码,修改后的函数 genphy_update_link 如下所示:

int genphy_update_link(struct phy_device *phydev)
{
	unsigned int mii_reg;

	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; 
    } 
	/*
	 * 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;
}

至此网络的复位引脚驱动修改完成,重新编译 uboot,然后将 u-boot.bin 烧写到 SD 卡中并
启动,至此U-Boot移植完毕。
需要使用secureCRT修改网络环境变量,如下:

setenv ipaddr 192.168.1.50      //开发板 IP 地址 
setenv ethaddr 00:04:9f:04:d2:35    //开发板网卡 MAC 地址 
setenv gatewayip 192.168.1.1     //开发板默认网关 
setenv netmask 255.255.255.0    //开发板子网掩码 
setenv serverip 192.168.1.102    //服务器地址,也就是 Ubuntu 地址 
saveenv              //保存环境变量 

大功告成!

你可能感兴趣的:(嵌入式Linux,嵌入式)