目錄
1.修改 Makefile
2.新增配置文件
3.新增設備樹文件
4.新建編譯腳本
5.修改 CPU 頻率
6.EMMC 適配
7.網絡驅動適配
1.修改 Makefile
修改頂層 Makefile 中的架構信息 ARCH 和交叉編譯器 CROSS_COMPILE,修改后不需要在執行 make 時手動指定這兩個變量的值:
# Makefile
# ARCH ?= $(SUBARCH)
# CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabihf-
2.新增配置文件
復制 arch/arm/configs 目錄中的 imx_v7_mfg_defconfig 配置文件,重命名為 imx_alientek_emmc_defconfig
屏蔽其中的 CONFIG_ARCH_MULTI_V6 配置項 (禁用 ARMv6 的相關配置):
// arch/arm/configs/imx_alientek_emmc_defconfig
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_ARCH_MULTI_V6=y
CONFIG_ARCH_MXC=y
# CONFIG_MACH_MX31ADS is not set
執行以下命令編譯配置文件,生成 .config 配置文件:
make imx_alientek_emmc_defconfig
3.新增設備樹文件
基于 EVK 開發板的設備樹 imx6ull-14x14-evk.dts 進行修改,復制該設備樹并命名為 imx6ull-alientek-emmc.dts
將 imx6ull-alientek-emmc.dts 中的 usdhc2 節點 (EMMC) 替換為 arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts 中的 usdhc2 節點:
// arch/arm/boot/dts/imx6ull-alientek-emmc.dts
&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";
};
在 arch/arm/boot/dts/Makefile 中新增正點原子開發板的設備樹編譯配置項:
# arch/arm/boot/dts/Makefile
dtb-$(CONFIG_SOC_IMX6ULL) += \...imx6ull-alientek-emmc.dtb
4.新建編譯腳本
新建編譯腳本 build.sh:
#!/bin/bash
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- -j8
為該腳本賦予可執行權限:
chmod +x build.sh
運行腳本進行編譯:
./build.sh
5.修改 CPU 頻率
/sys/bus/cpu/devices/cpu0/cpufreq 目錄中保存了 CPU 頻率相關的文件,這些文件的含義如下:
-
cpuinfo_cur_freq:當前 CPU 的工作頻率,從 CPU 寄存器讀取的工作頻率;
-
cpuinfo_max_freq:處理器所能運行的最高工作頻率 (單位 KHz);
-
cpuinfo_min_freq:處理器所能運行的最低工作頻率 (單位 KHz);
-
cpuinfo_transition_latency:處理器切換頻率所需時間 (單位 ns);
-
scaling_available_frequencies:處理器支持的頻率列表 (單位 KHz);
-
scaling_available_governors:內核支持的所有 governor 調頻類型;
-
scaling_cur_freq:保存 cpufreq 模塊緩存的當前 CPU 頻率,不會對 CPU 硬件寄存器進行檢查;
-
scaling_driver:保存當前 CPU 所使用的調頻驅動;
-
scaling_governor:governor 調頻策略,Linux 支持以下調頻策略:
-
Performance:最高性能,直接使用最高頻率,不考慮耗電;
-
Interactive:一開始使用最高頻率,然后根據 CPU 負載慢慢降低;
-
Powersave:省電模式,通常以最低頻率運行,系統性能會受影響,一般不使用;
-
Userspace:可以在用戶空間手動調節頻率;
-
Ondemand:定時檢查負載,并根據負載調節頻率,低負載時降低 CPU 頻率,高負載時提高 CPU 頻率;
-
-
scaling_max_freq:governor 調頻可設置的最高頻率;
-
cpuinfo_min_freq:governor 調頻可設置的最低頻率;
/sys/devices/system/cpu/cpu0/cpufreq/stats 目錄中包含 CPU 運行頻率的統計情況,例如 CPU 在各個頻率下的運行時間及變頻次數,使用以下命令查看 CPU 當前頻率:
cat cpuinfo_cur_freq
從中可以看出當前 CPU 的工作頻率為 792MHz:
通過 scaling_available_frequencies 文件查看 CPU 支持的工作頻率:
可以看出當前 CPU 支持的工作頻率為:198MHz、396MHz、528MHz 和 792MHz
通過查看 /stats 目錄下的 time_in_state 文件,可以獲取 CPU 在各頻率下的工作時間,命令如下:
cat /sys/bus/cpu/devices/cpu0/cpufreq/stats/time_in_state
通過修改 imx_alientek_emmc_defconfig 配置文件,設置 CPU 的調頻策略:
// arch/arm/configs/imx_alientek_emmc_defconfig
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
在其中添加 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 設置默認的調頻策略為 ONDEMAND:
// arch/arm/configs/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_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
6.EMMC 適配
正點原子 IMX6ULL 開發板的 EMMC 支持 8-bit 總線位寬,EVK 開發板默認使用 4-bit 的位寬,需要修改 EMMC 對應的 usdhc2 節點,硬件原理圖如下所示:
設備樹中 EMMC 模塊的引腳定義如下:
// arch/arm/boot/dts/imx6ull-alientek-emmc.dtspinctrl_usdhc2_8bit: usdhc2grp_8bit {fsl,pins = <MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059>;};pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {fsl,pins = <MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9>;};pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {fsl,pins = <MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9>;};
一共定義了三組引腳,分別為默認引腳配置、100MHz 引腳配置、200MHz 引腳配置,引腳相關的配置項由 drivers/pinctrl/freescale/pinctrl-imx.c 文件中的 imx_pinctrl_parse_groups() 函數負責解析
在設備樹中修改 EMMC 對應的節點信息:
-
pinctrl-names 為每組引腳的名稱:default、state_100mhz、state_200mhz;
-
pinctrl-x (x = 0~2) 為對應的三組引腳;
-
bus-width 為總線位寬 (8-bit);
-
non-removable 表示該節點的引腳不支持熱插拔;
-
no-1-8-v 表示不要使用 1.8V 的電壓驅動 EMMC (驅動電壓應該為 3.3V);
-
status 表示引腳狀態,okay 表示使能;
// arch/arm/boot/dts/imx6ull-alientek-emmc.dts
&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;no-1-8-v;status = "okay";
};
配置完成后將 EMMC 的總線位寬設置為 8-bit,并設置了對應的引腳,同時新增禁止 1.8V 驅動的配置項
7.網絡驅動適配
EVK 開發板的 PHY 芯片為 KSZ8081,正點原子開發板的 PHY 芯片為 LAN8720A,需要修改相關引腳
ENET1 的復位引腳 ENET1_RST 與 SoC 的 SNVS_TAMPER7 引腳連接
ENET2 的復位引腳 ENET2_RST 與 SoC 的 SNVS_TAMPER8 引腳連接
EVK 開發板將這兩個引腳用于 SPI4,因此需要在對應的節點中將其刪除,解除引腳占用:
// arch/arm/boot/dts/imx6ull-alientek-emmc.dtspinctrl_spi4: spi4grp {fsl,pins = <......MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x70a1MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x80000000>;};
在 SPI4 的節點中將引腳引用刪除:
// arch/arm/boot/dts/imx6ull-alientek-emmc.dtsspi4 {...pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;...cs-gpios = <&gpio5 7 0>;...};
在 iomuxc_snvs 節點中添加復位引腳:
// arch/arm/boot/dts/imx6ull-alientek-emmc.dts
&iomuxc_snvs {...pinctrl_enet1_reset: enet1resetgrp {fsl,pins = <MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0>;};pinctrl_enet2_reset: enet2resetgrp {fsl,pins = <MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0>;};
修改時鐘引腳,將時鐘引腳的配置值由 0x4001b031 修改為 0x4001b009:
// arch/arm/boot/dts/imx6ull-alientek-emmc.dtspinctrl_enet1: enet1grp {fsl,pins = <...MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009>;};pinctrl_enet2: enet2grp {fsl,pins = <...MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009>;};
修改 FEC1 和 FEC2 節點的 pinctrl-0 屬性,添加復位引腳,低電平有效,復位時長 200ms:
// arch/arm/boot/dts/imx6ull-alientek-emmc.dts
&fec1 {...pinctrl-0 = <&pinctrl_enet1&pinctrl_enet1_reset>;...phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;phy-reset-duration = <200>;
};&fec2 {...pinctrl-0 = <&pinctrl_enet2&pinctrl_enet2_reset>;...phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;phy-reset-duration = <200>;
ENET1 的 LAN8720A 地址為 0x0,ENET2 的 LAN8720A 地址為 0x1,在設備樹中修改:
// arch/arm/boot/dts/imx6ull-alientek-emmc.dts
&fec2 {...mdio {...ethphy0: ethernet-phy@0 {...smsc,disable-energy-detect;reg = <0>;};ethphy1: ethernet-phy@1 {...smsc,disable-energy-detect;reg = <1>;};
屬性 smsc,disable-energy-detect 表示 PHY 芯片屬于 SMSC,Linux 會根據該屬性查找對應的驅動
drivers/net/ethernet/freescale/fec_main.c 中修改 fec_probe() 函數,添加引腳復位操作:
// drivers/net/ethernet/freescale/fec_main.c
static int
fec_probe(struct platform_device *pdev)
{...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);
在配置文件 arch/arm/configs/imx_alientek_emmc_defconfig 中添加 SMSC PHY 使能配置項,同時注釋 AT803 PHY 的配置項:
// arch/arm/configs/imx_alientek_emmc_defconfig
CONFIG_SMSC_PHY=y# CONFIG_AT803X_PHY=y
在 drivers/net/phy/smsc.c 中新增復位操作:
// drivers/net/phy/smsc.c
#include <linux/of_gpio.h>
#include <linux/io.h>
...
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);}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;
}
網絡配置完成后終端顯示如下信息:
fec 20b4000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
fec 20b4000.ethernet eth0: Link is Down
IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
這是因為網口引腳和屏幕引腳存在復用,屏幕上有三個電阻用于識別屏幕,導致引腳驅動能力不足,需要修改設備樹中屏幕相關引腳的驅動能力,相關文章鏈接:http://www.openedv.com/forum.php?mod=viewthread&tid=322548
修改完成后查看網口是否存在:
修改網口的 IP 地址:
ifconfig eth0 172.17.40.88
ping 虛擬機檢查是否可以通信: