正点原子imx6ull-mini开发板移植linux内核全过程

10 篇文章 0 订阅
8 篇文章 0 订阅

一:默认配置文件的移植与设备树移植

1.1:在/arm/configs里复制一份imx_v7_mfg_defconfig文件并改名

1.2:在/arm/boot/dts 复制一份imx6ull-14x14-evk.dts文件并改名

1.3:在arch/arm/boot/dts的Makefile文件内添加我们自己的dtb文件名

配置完后,我们改一下脚本的默认配置项编译一下,确保没错误再进行下一步

#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j2

二:CPU主频和网络驱动修改

2.1: 主频模式选择,修改 imx_alientek_emmc_defconfig

#CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y

不知为何,我的这个配置文件默认是没有默认配置。其他4种策略也都用了。通过图形界面更方便

最好是配置成ondmand模式,性能模式是真的发热。不建议超频使用,开发板本来就没散热,原子的性能模式摸着板子都很热。别的主频不到792M的不建议超频到700M,使用自己支持的最大主频即可。

2.2:emmc的8线驱动使能

把原来的~/linux/arch/arm/boot/dts/imx6ull_alientek_emmc.dts的&usdhc2替换

&usdhc2 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc2_8bit>;
	pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
	bus-width = <8>;
	non-removable;
	status = "okay";
};

2.3:网络驱动修改

2.3.1:替换掉spi4grp,或者说删除掉后两行,后两行是LAN的复位引脚。

		pinctrl_spi4: spi4grp {
                        fsl,pins = <
                                MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10        0x70a1
                                MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11        0x70a1
                               
                        >;
                };

2.3.2:找到spi4,进行替换,目的也是删掉对GPIO5的7、8号引脚的引用

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

2.3.3:在597行添加enet复位引脚信息,或者是在iomuxc_snvs节点尾部

/*enet1 reset zuozhongkai*/
				pinctrl_enet1_reset: enet1resetgrp {
					fsl,pins = <
						/* used for enet1 reset */
						MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0
						>;
				};
				/*enet2 reset zuozhongkai*/
				pinctrl_enet2_reset: enet2resetgrp {
					fsl,pins = <
						/* used for enet2 reset */
						MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0
						>;
				};

2.3.4:修改分别为 ENET1 和 ENET2 的网络时钟引脚配置信息,将这两个引脚的电 气属性值改为 0x4001b009,原来默认值为 0x4001b031

		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 0x4001b009

			>;
		};

		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 0x4001b009

			>;
		};

2.3.5: 修改 fec1 和 fec2 节点的 pinctrl-0 属性

&fec1 {
	pinctrl-names = "default";
	pinctrl-0 =  <&pinctrl_enet1
							  &pinctrl_enet1_reset>;
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	status = "okay";
};

&fec2 {
	pinctrl-names = "default";
	pinctrl-0 =  <&pinctrl_enet2
							  &pinctrl_enet2_reset>;
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	status = "okay";

2.3.6: 修改 LAN8720A 的 PHY 地址,主要还是看你开发板的版本,我的迷你是v2.2.不用修改。低于1.8好像就要修改来着

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

如果需要修改,就是

mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy0: ethernet-phy@0 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <0>;
		};

		ethphy1: ethernet-phy@1 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <1>;
		};
	};

仅仅编译设备树文件 make dtbs

2.3.6:修改 fec_main.c 文件

要 在 I.MX6ULL 上 使 用 LAN8720A , 需 要 修 改 一 下 Linux 内 核 源 码 , 打 开 drivers/net/ethernet/freescale/fec_main.c,找到函数 fec_probe,在 fec_probe 中加入如下代码

用vscode打开后在3452行以后加入,

	/* 设置 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);

2.3.7:图形化配置使能LAN8720驱动

退出并重新编译linux内核

检查一下defconfig,如果不是SMSC再进入一次图形化配置界面,不知道为啥我的defconfig好像没有同步更新。

2.3.8:修改 smsc.c 文件

替换掉原有的smsc_phy_reset,以实现每次调用都会进行一次LAN8720A软复位

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) /* FEC1 */ {
		np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
		if(np == NULL) {
			return -EINVAL;
		}
	}
	if(phydev->addr == 1) /* FEC2 */ {
		np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
		if(np == NULL) {
			return -EINVAL;
		}
	}
	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);


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

	
	}

因为修改后的 smsc_phy_reset 函数用到了 gpio_direction_output 和 gpio_set_value 这两个函数,需要添加头文件

#include <linux/of_gpio.h>
#include <linux/io.h>

给我报了一堆警告,不知道是啥

通过设置bootcmd之后,boot进入linux系统。ifconfig可以显示网卡信息

在这之前一定要配置好bootargs,它决定了文件系统的挂载

bootargs=console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw
bootcmd=tftp 80800000 zImage;tftp 83000000 imx6ull_alientek_emmc.dtb;bootz 80800000 - 83000000;

到此linux内核就算移植完成,三大金刚完成两个

三:总结

linux内核的移植跟uboot很像,配置defconfig或者经过图形化界面配置。然后就是设备树的依赖dbs文件的各种修改,像时钟、emmc8线、网络驱动修改。最麻烦的就是网络驱动,设计很多个文件,其实就是那两个IO口的倒腾,然后就是硬软复位问题,LAN8720A必须要软复位,软复位就是操作其内部寄存器,硬复位就是芯片的一个专门用来复位的引脚,像单片机的RST脚。总共修改了对应IO的时钟、属性、驱动。

  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值