Linux | 移植NXP官方linux内核到imx6ull开发板(4.1.15)
Posted Mculover666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux | 移植NXP官方linux内核到imx6ull开发板(4.1.15)相关的知识,希望对你有一定的参考价值。
一、NXP官方linux内核
1. 下载
NXP官方linux仓库地址为:https://github.com/Freescale/linux-fslc。
这里为了保持版本统一,使用正点原子资料包中提供的原厂linux:linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2
(版本是4.1.15)。
2. 编译
安装lzop库:
sudo apt-get install lzop
设置临时环境变量:
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
清理构建:
make distclean
查看arch/arm/configs目录下imx6ull相关的单板:
mfg标识表示可以使用NXP的MfgTool工具烧写,所以使用imx_v7_mfg_defconfig
配置文件:
make imx_v7_mfg_defconfig
配置好之后编译:
make
编译成功后,进入arch/arm/boot
目录可以看到编译出的linux镜像,其中zImage是经过压缩后的镜像:
在dts目录下是编译出的设备树文件:
3. 下载到开发板
将内核镜像和设备树文件拷贝到tftp根目录中:
cp zImage ~/tftp_root/
cp dts/imx6ull-14x14-evk.dtb ~/tftp_root/
接下来在开发板上进入uboot,确保bootargs环境变量的值如下:
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
加载这两个文件:
setenv bootargs 'bootargs=console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-evk.dtb
启动内核:
bootz 80800000 - 83000000
4. 启动结果分析
因为EMMC中有出厂烧写的文件系统,所以Linux内核成功挂载了根文件系统,启动成功,但是也有一些问题:
- LCD屏幕无显示;
- 网卡eth0报错,但是可以获取到ip,可以ping通主机;
接下来,我们就基于NXP官方提供的linux,针对正点原子imx6ull开发板进行一些配置参数的修改,修复LCD和网络问题。
二、移植linux内核
1. 新建单板
(1)新建单板配置文件
进入 arch/arm/configs 目录,复制一份新的单板文件:
cd arch/arm/configs
cp imx_v7_mfg_defconfig imx_atk_emmc_defconfig
(2)新建设备树文件
进入 arch/arm/boot/dts 目录,复制一份新的设备树文件:
cd arch/arm/boot/dts/
cp imx6ull-14x14-evk.dts imx6ull-atk-emmc.dts
接着修改同级目录下的Makefile,添加一行:
dtb-$(CONFIG_SOC_IMX6ULL) += \\
imx6ull-14x14-ddr3-arm2.dtb \\
imx6ull-14x14-ddr3-arm2-adc.dtb \\
imx6ull-14x14-ddr3-arm2-cs42888.dtb \\
imx6ull-14x14-ddr3-arm2-ecspi.dtb \\
imx6ull-14x14-ddr3-arm2-emmc.dtb \\
imx6ull-14x14-ddr3-arm2-epdc.dtb \\
imx6ull-14x14-ddr3-arm2-flexcan2.dtb \\
imx6ull-14x14-ddr3-arm2-gpmi-weim.dtb \\
imx6ull-14x14-ddr3-arm2-lcdif.dtb \\
imx6ull-14x14-ddr3-arm2-ldo.dtb \\
imx6ull-14x14-ddr3-arm2-qspi.dtb \\
imx6ull-14x14-ddr3-arm2-qspi-all.dtb \\
imx6ull-14x14-ddr3-arm2-tsc.dtb \\
imx6ull-14x14-ddr3-arm2-uart2.dtb \\
imx6ull-14x14-ddr3-arm2-usb.dtb \\
imx6ull-14x14-ddr3-arm2-wm8958.dtb \\
imx6ull-14x14-evk.dtb \\
imx6ull-14x14-evk-btwifi.dtb \\
imx6ull-14x14-evk-emmc.dtb \\
imx6ull-14x14-evk-gpmi-weim.dtb \\
imx6ull-14x14-evk-usb-certi.dtb \\
imx6ull-9x9-evk.dtb \\
imx6ull-atk-emmc.dtb \\
imx6ull-9x9-evk-btwifi.dtb \\
imx6ull-9x9-evk-ldo.dtb
(3)编译测试
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
make clean
make imx_atk_emmc_defconfig
make
(4)烧写测试
编译完成后将zImage和设备树文件拷贝到tftp根目录,加载:
tftp 80800000 zImage
tftp 83000000 imx6ull-atk-emmc.dtb
bootz 80800000 - 83000000
内核启动成功。
2. 修改网络驱动
(1)修改LAN8720A的复位引脚驱动
修改设备树文件arch/arm/boot/dts/imx6ull-atk-emmc.dts
,搜索 GPIO5_IO07、GPIO5_IO08,发现已被spi4使用,删除这两行后,代码如下:
pinctrl_spi4: spi4grp {
fsl,pins = <
MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x70a1
MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x70a1
>;
};
接着再找到spi4,删除与这两个GPIO相关的代码,删除后如下:
spi4 {
compatible = "spi-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi4>;
status = "okay";
gpio-sck = <&gpio5 11 0>;
gpio-mosi = <&gpio5 10 0>;
num-chipselects = <1>;
#address-cells = <1>;
#size-cells = <0>;
gpio_spi: gpio_spi@0 {
compatible = "fairchild,74hc595";
gpio-controller;
#gpio-cells = <2>;
reg = <0>;
registers-number = <1>;
registers-default = /bits/ 8 <0x57>;
spi-max-frequency = <100000>;
};
};
接着将复位引脚加入到 pinctrl_enet1 的代码中:
pinctrl_enet1: enet1grp {
fsl,pins = <
MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
MX6UL_PAD_SNVS_TAMPER7__GOIO5_IO07 0x10B0
>;
};
接着将复位引脚加入到 pinctrl_enet2 的代码中:
pinctrl_enet2: enet2grp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
MX6UL_PAD_SNVS_TAMPER8__GOIO5_IO08 0x10B0
>;
};
接着搜索fec,添加网络驱动复位引脚使用,添加后的代码如下:
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
phy-mode = "rmii";
phy-handle = <ðphy0>;
phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
phy-reset-duration = <200>;
status = "okay";
};
&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
phy-mode = "rmii";
phy-handle = <ðphy1>;
phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
phy-reset-duration = <200>;
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@2 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <2>;
};
ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
};
};
};
(2)修改LAN8720的PHY地址
修改设备树文件arch/arm/boot/dts/imx6ull-atk-emmc.dts
,搜索 fec,修改mdio节点中的值:
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
smsc,disable-energy-detect;
reg = <0>;
};
ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
smsc,disable-energy-detect;
reg = <1>;
};
};
至此,设备树修改完成。
(3)修改fec_main.c文件
修改drivers/net/ethernet/freescale/fec_main.c
文件,找到函数fec_probe,在函数开头添加如下代码:
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);
fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
(4)修改PHY驱动源码
修改drivers/net/phy/smsc.c
文件,添加两个头文件:
#include <linux/of_gpio.h>
#include <linux/io.h>
然后找到smsc_phy_reset
函数,修改之后如下:
static int smsc_phy_reset(struct phy_device *phydev)
{
int err, phy_reset;
int msec = 1;
struct device_node *np;
int timeout = 50000;
if (phydev->addr == 0) {
np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
} else if (phydev->addr = 1) {
np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
}
if (!np) {
return -EINVAL;
}
/* A sane reset duration should not be longer than 1s */
err = of_property_read_u32(np, "phy-reset-duration", &msec);
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);
int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
if (rc < 0)
return rc;
/* If the SMSC PHY is in power down mode, then set it
* in all capable mode before using it.
*/
if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
/* set "all capable" mode and reset the phy */
rc |= MII_LAN83C185_MODE_ALL;
phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
}
phy_write(phydev, MII_BMCR, BMCR_RESET);
/* wait end of reset (max 500 ms) */
do {
udelay(10);
if (timeout-- == 0)
return -1;
rc = phy_read(phydev, MII_BMCR);
} while (rc & BMCR_RESET);
return 0;
}
(5)配置Linux内核,使能LAN8720驱动
make imx_atk_emmc_defconfig
make menuconfig
报错:
fatal error: curses.h: No such file or directory
安装库来解决:
sudo apt-get install libncurses5-dev
使能Device Drivers\\Network device support\\ PHY Device support and infrastructure\\Drivers for SMSC PHYs
:
保存到.config,然后退出。
(6)编译测试
重新编译内核,烧写内核和设备树,测试网络驱动。
ping主机测试:
至此,网络驱动修改成功。
以上是关于Linux | 移植NXP官方linux内核到imx6ull开发板(4.1.15)的主要内容,如果未能解决你的问题,请参考以下文章
i.MX6ULL系统移植 | 移植NXP官方 linux 5.4 内核