移植Linux4.14.13到imx6ull

2022-08-23 14:18:07 浏览数 (1)

1 环境

  • 正点原子imx6ull开发板
  • kernel4.14.13

2 移植目标

开发板能够正常启动,并且网络功能正常,能使用nfs、tftp等方式,便于调试。

3 移植过程

3.1 创建自己的板级配置文件-defconfig文件

复制一份imx_v6_v7_defconfig,这里我命名为dfos_mini_defconfig。

3.2 创建配套的dts文件

复制一份imx6ull-14x14-evk.dts,重命名为dfos.dts。同时还要修改Makefile,让内核编译出dfos.dtb。

3.3 修改内核顶层Makefile

3.4 编译

执行make dfos_mini_defconfig编译出.config,然后再执行make编译出镜像。uboot通过tftp的方式下载镜像并且启动内核。这里插入我开发板里uboot的环境变量,关于网络功能相关配置:

代码语言:javascript复制
setenv gatewayip "192.168.1.1"
setenv ipaddr "192.168.1.110"
setenv netmask "255.255.255.0"
setenv serverip "192.168.1.104"
setenv bootcmd "tftp 80800000 zImage; tftp 83000000 dfos.dtb; bootz 80800000 - 83000000"
setenv bootargs "console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.104:/home/zrc/nfs/rootfs,proto=tcp rw ip=192.168.1.100:192.168.1.104:192.168.1.1:255.255.255.0::eth0:off"
setenv ethaddr "00:04:9f:04:d2:35"

3.5 启动

如下图,内核启动到挂载nfs文件系统前提示打开eth0失败,随后挂载nfs失败。因此需要对网络驱动进行适配,参考正点原子提供的教程移植到4.14.13。

3.6 网络驱动修改

3.6.1 修改imx6ul-14x14-evk.dts

注意,这个修改的是imx6ul-14x14-evk.dts,不是dfos.dts,也不要看成imx6ull-14x14-evk.dts,我们创建的dfos.dts会调imx6ul-14x14-evk.dts。

代码语言:javascript复制
dfos.dts  
  |-- imx6ul-14x14-evk.dts  
    |-- imx6ul.dtsi
3.6.1.1 修改fec1和fec2节点
3.6.1.2 修改iomuxc节点
3.6.1.3 修改MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1和2

原值是0x4001b031,修改成0x4001b009.

3.6.2 在arch/arm/boot/dts/imx6ul-pinfunc.h增加2个宏定义

这两个宏就是在3.6.1.2 修改iomuxc节点里用到了。

代码语言:javascript复制
#define MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07		0x0024 0x0068 0x0000 0x5 0x0
#define MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08		0x0028 0x006C 0x0000 0x5 0x0

3.6.3 修改drivers/net/ethernet/freescale/fec_main.c

增加set_enet_tx_clk函数,并在fec_probe函数最开始调用它,设置寄存器的 SION 位为 1。

代码语言:javascript复制
static void set_enet_tx_clk(void)
{
	/*
	 * 设置 MX6UL_PAD_ENET1_TX_CLK 和 MX6UL_PAD_ENET2_TX_CLK
	 * 这两个 IO 的复用寄存器的 SION 位为 1。
	 */
	void __iomem *IMX6U_ENET1_TX_CLK;
	void __iomem *IMX6U_ENET2_TX_CLK;

	IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);
	writel(0X14, IMX6U_ENET1_TX_CLK);

	IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);
	writel(0X14, IMX6U_ENET2_TX_CLK);
}

static int
fec_probe(struct platform_device *pdev)
{
               ···省略···
  set_enet_tx_clk();
}

3.6.4 修改drivers/net/phy/smsc.c

增加2个头文件,df_phy_reset函数,并在smsc_phy_reset调用df_phy_reset复位phy。

代码语言:javascript复制
#include <linux/of_gpio.h>
#include <linux/io.h>

static void df_phy_reset(struct phy_device *phydev)
{
	int err;
	struct device_node *np;
	int msec = 1;
	int phy_reset;

	if(phydev->mdio.addr == 0) { /* FEC1 */
		np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
		if(np == NULL) {
			pr_err("%s %d: get np failn", __func__, __LINE__);
			return;
		}
	}

	if(phydev->mdio.addr == 1) { /* FEC2 */
		np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
		if(np == NULL) {
			pr_err("%s %d: get np failn", __func__, __LINE__);
			return;
		}
	}

	err = of_property_read_u32(np, "phy-reset-duration", &msec);
	/* A sane reset duration should not be longer than 1s */
	if (!err && msec > 1000)
		msec = 1;

	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
	if (!gpio_is_valid(phy_reset))
		return;

	gpio_direction_output(phy_reset, 0);
	gpio_set_value(phy_reset, 0);
	msleep(msec);
	gpio_set_value(phy_reset, 1);
}

static int smsc_phy_reset(struct phy_device *phydev)
{
···省略···
	df_phy_reset(phydev);
···省略···
}

至此,网络驱动修改完成,重新编译并启动。

测试

启动可以看到相关网络信息的打印,并且已经进入到根文件系统nfsroot,至此,kernel4.14.13算是成功移植到imx6ull上了,最重要的网络功能已经能正常使用。

0 人点赞