sudo apt-get install lzop
#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean #注意会清掉.config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig #可选
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
arch/arm/configs目录下是各种开发板的xxx_defconfig文件
arch/arm/boot/dts目录下是各种开发板的dts、dtsi文件和编译出来的dtb文件
arch/arm/boot目录下保存编译出来的Image和zImage镜像文件
#为了方便编译,可以在顶层MAKEFILE文件指定ARCH和CROSS_COMPILE
#修改内容如下
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabihf-
cd arch/arm/configs
cp imx_v7_mfg_defconfig imx_ht_defconfig #mfg可以用于mfgtools烧录
cd arch/arm/boot/dts
cp imx6ull-14x14-evk.dts imx6ull-ht.dts
#修改arch/arm/boot/dts/Makefile添加编译项
dtb-$(CONFIG_SOC_IMX6ULL) +=下添加
imx6ull-ht.dtb
make menuconfig
CPU Power Management
-> CPU Frequency scaling
-> CPU Frequency scaling
-> Default CPUFreq governor
选择performance这样CPU始终处于最高频
linux内核驱动里面的EMMC默认是4线模式的,4线模式的没有8线模式的速度快。但linux设备文件中也配置了8线模式,所以我们主要修改设备树文件即可。
#修改设备树EMMC接口是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";
};
#官方的KSZ8081被更换成LAN8720A,导致复位引脚发生了变化,故要修改复位引脚
# 进入设备树文件
#1 删去被占用的引脚配置(全局搜索被占用的引脚并删去,pinctrl--GPIO5_IO07/GPIO5_IO08,gpio子系统--
pinctrl_spi4: spi4grp {
fsl,pins = <
MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x70a1
MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x70a1
/*MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x70a1
MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x80000000*/
>;
};
spi4 {
compatible = "spi-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi4>;
/* pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; */
status = "okay";
gpio-sck = <&gpio5 11 0>;
gpio-mosi = <&gpio5 10 0>;
/* cs-gpios = <&gpio5 7 0>; */
...
};
#2 修改ent1时钟参考引脚属性!这一步很关键,不做则会出现网络驱动反复开关的情形。再增加我们复位引脚的pinctrl子系统。
pinctrl_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
>;
};
#snvs引脚统一在iomuxc_snvs节点中进行复用管理
&iomuxc_snvs {
...
imx6ul-evk {
...
/*enet1 reset*/
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
>;
};
...
};
#3 修改PHY地址 fec1和fec2节点增加gpio子系统用于复位,再增加一个duration属性。mdio节点用于设置phy地址。
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1
&pinctrl_ent1_reset>;
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
&pinctrl_enet2_reset>;
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@0 {
compatible = "ethernet-phy-ieee802.3-c22";
smsc,disable-energy-detect //表示芯片是smsc公司的
reg = <0>;
};
ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
smsc,disable-energy-detect;
reg = <1>;
};
};
};
#4 修改fec_main.c中的模块初始化函数fec_probe(struct platform_device *pdev),添加以下代码:
static int fec_probe(struct platform_device *pdev)
{
struct fec_enet_private *fep;
struct fec_platform_data *pdata;
struct net_device *ndev;
int i, irq, ret = 0;
struct resource *r;
const struct of_device_id *of_id;
static int dev_id;
struct device_node *np = pdev->dev.of_node, *phy_node;
int num_tx_qs;
int num_rx_qs;
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);
...
#5 配置Linux内核,使能LAN8720驱动
make menuconfig
-> Device Drivers
-> Network device support
-> PHY Device support and infrastructure
-> Drivers for SMSC PHYs
#6 修改smsc.c文件: 使用LAN8720A需要对LAN8720A进行一次软复位,LAN8720A驱动文件就是smsc.c,内部的smsc_phy_reset就是复位函数.
#需要再前面添加头文件
#include
#include
static int smsc_phy_reset(struct phy_device *phydev)
{
int err, phy_reset;
int msec = 1;
struct device_node *np;
if(phydev->addr == 0) /* FEC1 */ {
np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000"); #获取FEC1网卡对应的设备节点
if(np == NULL) {
return -EINVAL;
}
}
if(phydev->addr == 1) /* FEC2 */ {
np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000"); #回去FEC2对应的设备节点
if(np == NULL) {
return -EINVAL;
}
}
err = of_property_read_u32(np, "phy-reset-duration", &msec); #从设备树节点获取复位时间信息,存进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); #获得复位IO信息
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) */
int timeout = 50000;
do {
udelay(10);
if (timeout-- == 0)
return -1;
rc = phy_read(phydev, MII_BMCR);
} while (rc & BMCR_RESET);
return 0;
}
(1)menuconfig修改后默认保存在.config中,所以可以将.config直接另存为xxx_defconfig。
(2)通过menconfig中的save按钮,再输入相对路径。