Linux驱动之系统移植 您所在的位置:网站首页 linux系统版本有哪些 Linux驱动之系统移植

Linux驱动之系统移植

2023-01-12 12:06| 来源: 网络整理| 查看: 265

uboot版本:uboot2020.04 开发板:100ask_imx6ull_pro

拿到官方uboot后第一步先编译烧写测试, 查看哪些驱动可用, 哪些不可用. 根据开发板厂商提供的资料: 使用mx6ull_14x14_evk_defconfig配置进行修改 编译完成后将uboot设备树以及uboot.imx烧写到开发板中运行

CPU: i.MX6ULL rev1.1 792 MHz (running at 396 MHz) CPU: Industrial temperature grade (-40C to 105C) at 40C Reset cause: POR Model: i.MX6 ULL 14x14 EVK Board Board: MX6ULL 14x14 EVK DRAM: 512 MiB MMC: FSL_SDHC: 0, FSL_SDHC: 1 Loading Environment from MMC... *** Warning - bad CRC, using default environment [*]-Video Link 0 (480 x 272) [0] lcdif@21c8000, video In: serial Out: serial Err: serial switch to partitions #0, OK mmc1(part 0) is current device flash target is MMC:1 Net: Error: ethernet@20b4000 address not set. Error: ethernet@20b4000 address not set. Error: ethernet@20b4000 address not set. FEC: can't find phy-handle Error: ethernet@20b4000 address not set. Could not get PHY for FEC0: addr 2 Error: ethernet@20b4000 address not set. FEC: can't find phy-handle Error: ethernet@20b4000 address not set. Could not get PHY for FEC0: addr 2 No ethernet found.

显然网络不通, phy无法找到, 其次LCD需要关闭(uboot启动阶段非必要驱动LCD)

一, 添加自定义板子

参考文章官方uboot添加自定义板子 备注: uboot2020的图形界面配置文件在 arch/arm/mach-imx/mx6 全局搜索TARGET_MX6ULL_14X14_EVK找到的

二, 关闭LCD

在mx6ull_jzy_defconfig文件中

删除 CONFIG_DM_VIDEO=y

因为在mx6ull_jzy.c文件中有lcd的初始化函数: setup_lcd(void);有个编译选项为CONFIG_DM_VIDEO, 搜索这个就可以得到是在mx6ull_jzy_defconfig中定义了

三, 在设备树中修改网络驱动

官板与开发板的硬件原理图对比 由于开发板更换了官板的phy芯片所以需要修改PHY芯片配置 在mx6ull_jzy.c文件中找到网络驱动相关的函数: static int setup_fec(void)

#ifdef CONFIG_FEC_MXC static int setup_fec(void) { struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; int ret; /* * Use 50M anatop loopback REF_CLK1 for ENET1, * clear gpr1[13], set gpr1[17]. */ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK, IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK); /* * Use 50M anatop loopback REF_CLK2 for ENET2, * clear gpr1[14], set gpr1[18]. */ if (!check_module_fused(MX6_MODULE_ENET2)) { clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC2_MASK, IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK); } ret = enable_fec_anatop_clock(0, ENET_50MHZ); if (ret) return ret; if (!check_module_fused(MX6_MODULE_ENET2)) { ret = enable_fec_anatop_clock(1, ENET_50MHZ); if (ret) return ret; } enable_enet_clk(1); return 0; } int board_phy_config(struct phy_device *phydev) { phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x8190); if (phydev->drv->config) phydev->drv->config(phydev); return 0; } #endif

被CONFIG_FEC_MXC宏定义包含, 在mx6ull_jzy_defconfig中搜索得到: CONFIG_FEC_MXC=y 已经开启.

由于开发板使用了LAN8720的PHY芯片, 在mx6ull_jzy_defconfig把 CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ8XXX=y 这两个删除, 替换成 CONFIG_PHY_SMSC=y

因为在drivers/net/phy/Makefile中定义了一系列编译选项

# SPDX-License-Identifier: GPL-2.0+ # # (C) Copyright 2008 # Wolfgang Denk, DENX Software Engineering, [email protected]. obj-$(CONFIG_BITBANGMII) += miiphybb.o obj-$(CONFIG_B53_SWITCH) += b53.o obj-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o obj-$(CONFIG_MV88E6352_SWITCH) += mv88e6352.o obj-$(CONFIG_PHYLIB) += phy.o obj-$(CONFIG_PHYLIB_10G) += generic_10g.o obj-$(CONFIG_PHY_AQUANTIA) += aquantia.o obj-$(CONFIG_PHY_ATHEROS) += atheros.o obj-$(CONFIG_PHY_BROADCOM) += broadcom.o obj-$(CONFIG_PHY_CORTINA) += cortina.o obj-$(CONFIG_PHY_DAVICOM) += davicom.o obj-$(CONFIG_PHY_ET1011C) += et1011c.o obj-$(CONFIG_PHY_LXT) += lxt.o obj-$(CONFIG_PHY_MARVELL) += marvell.o obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o obj-$(CONFIG_PHY_NATSEMI) += natsemi.o obj-$(CONFIG_PHY_REALTEK) += realtek.o obj-$(CONFIG_PHY_SMSC) += smsc.o obj-$(CONFIG_PHY_TERANETICS) += teranetics.o obj-$(CONFIG_PHY_TI) += dp83867.o obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o obj-$(CONFIG_PHY_VITESSE) += vitesse.o obj-$(CONFIG_PHY_MSCC) += mscc.o obj-$(CONFIG_PHY_FIXED) += fixed.o obj-$(CONFIG_PHY_NCSI) += ncsi.o

跳转到smsc.c中发现开发板所用的芯片的定义:

static struct phy_driver lan8710_driver = { .name = "SMSC LAN8710/LAN8720", .uid = 0x0007c0f0, .mask = 0xffff0, .features = PHY_BASIC_FEATURES, .config = &genphy_config_aneg, .startup = &genphy_startup, .shutdown = &genphy_shutdown, };

修改设备树

第一步确定PHY芯片地址 mx6ull_jzy_defconfig中定义了 CONFIG_DEFAULT_DEVICE_TREE=“imx6ull-14x14-evk” 使用设备树imx6ull-14x14-evk 打开imx6ull-14x14-evk.dts

#include "imx6ull.dtsi" #include "imx6ul-14x14-evk.dtsi" #include "imx6ul-14x14-evk-u-boot.dtsi"

包含了三个dtsi, 全部打开, 并搜索phy关键字 在imx6ul-14x14-evk.dtsi中找到fec1和fec2的描述

&fec1 { pinctrl-names = "default"; pinctrl-0 = ; phy-mode = "rmii"; phy-handle = ; status = "okay"; }; &fec2 { pinctrl-names = "default"; pinctrl-0 = ; phy-mode = "rmii"; phy-handle = ; status = "okay"; mdio { #address-cells = ; #size-cells = ; ethphy0: ethernet-phy@2 { reg = ; micrel,led-mode = ; clocks = ; clock-names = "rmii-ref"; }; ethphy1: ethernet-phy@1 { reg = ; micrel,led-mode = ; clocks = ; clock-names = "rmii-ref"; }; }; };

然而其标签是&fec2说明这并不是最初的源头, 我们需要找到对饮的节点的驱动程序, 最好的办法就是fec2的compatible属性的定义 通过追溯所有imx6ull-14x14-evk.dts包含的设备树, 找到imx6ul.dtsi中描述了fec2

fec2: ethernet@20b4000 { compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec"; reg = ; interrupt-names = "int0", "pps"; interrupts = , ; clocks = , , , , ; clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "enet_out"; fsl,num-tx-queues=; fsl,num-rx-queues=; status = "disabled"; };

通过搜索 fsl,imx6ul-fec 这个关键字可以找到驱动程序

找到了drivers/net/fec_mxc.c中

static const struct udevice_id fecmxc_ids[] = { { .compatible = "fsl,imx28-fec" }, { .compatible = "fsl,imx6q-fec" }, { .compatible = "fsl,imx6sl-fec" }, { .compatible = "fsl,imx6sx-fec" }, { .compatible = "fsl,imx6ul-fec" }, { .compatible = "fsl,imx53-fec" }, { .compatible = "fsl,imx7d-fec" }, { .compatible = "fsl,mvf600-fec" }, { .compatible = "fsl,imx8qm-fec" }, { } }; U_BOOT_DRIVER(fecmxc_gem) = { .name = "fecmxc", .id = UCLASS_ETH, .of_match = fecmxc_ids, .ofdata_to_platdata = fecmxc_ofdata_to_platdata, .probe = fecmxc_probe, .remove = fecmxc_remove, .ops = &fecmxc_ops, .priv_auto_alloc_size = sizeof(struct fec_priv), .platdata_auto_alloc_size = sizeof(struct eth_pdata), };

在device_get_phy_addr函数中发现获取phy地址, 读取的是phy-handle属性中的reg的第0个描述

static int device_get_phy_addr(struct udevice *dev) { struct ofnode_phandle_args phandle_args; int reg; if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, &phandle_args)) { debug("Failed to find phy-handle"); return -ENODEV; } reg = ofnode_read_u32_default(phandle_args.node, "reg", 0); return reg; }

fec2的reg第0个描述是0x1.无需修改

第二步对PHY芯片进行硬复位, 即对复位引脚进行操作 在drivers/net/fec_mxc.c中的fecmxc_probe函数中是有复位函数调用的:

static int fecmxc_probe(struct udevice *dev) { ... #if CONFIG_IS_ENABLED(DM_GPIO) fec_gpio_reset(priv); #endif ... }

CONFIG_IS_ENABLED(DM_GPIO)这个宏表示 CONFIG_DM_GPIO是否使能了

查看fec_gpio_reset(priv);函数

/* FEC GPIO reset */ static void fec_gpio_reset(struct fec_priv *priv) { debug("fec_gpio_reset: fec_gpio_reset(dev)\n"); if (dm_gpio_is_valid(&priv->phy_reset_gpio)) { dm_gpio_set_value(&priv->phy_reset_gpio, 1); mdelay(priv->reset_delay); dm_gpio_set_value(&priv->phy_reset_gpio, 0); if (priv->reset_post_delay) mdelay(priv->reset_post_delay); } }

dm_gpio_is_valid(&priv->phy_reset_gpio)知道 如果phy_reset_gpio是有效的才会进入初始化. 搜索phy_reset_gpio找到:

ret = gpio_request_by_name(dev, "phy-reset-gpios", 0, &priv->phy_reset_gpio, GPIOD_IS_OUT);

原来是通过读取设备树中的phy-reset-gpios这个属性, 因此,需要加这个属性. 回到imx6ul-14x14-evk.dtsi文件, 在&fec2中添加属性phy-reset-gpios = ; 模仿spi4节点中的pinctrl-assert-gpios = ;来写的; 初始化的过程还有用到reset_delay这个变量, 搜索得到 priv->reset_delay = dev_read_u32_default(dev, “phy-reset-duration”, 1); 是这么来, 所以要添加phy-reset-duration属性, 值在LAN8720芯片手册中说明, 初始化引脚要保持25以上, 因此设置phy-reset-duration = ;

&fec2 { pinctrl-names = "default"; pinctrl-0 = ; phy-mode = "rmii"; phy-handle = ; phy-reset-gpios = ; phy-reset-duration = ; status = "okay"; mdio { #address-cells = ; #size-cells = ; ethphy0: ethernet-phy@2 { reg = ; micrel,led-mode = ; clocks = ; clock-names = "rmii-ref"; }; ethphy1: ethernet-phy@1 { reg = ; micrel,led-mode = ; clocks = ; clock-names = "rmii-ref"; }; }; };

在设备树中加上 gpio5-6的初始化. 找到合适的位置添加: MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x79 只要会被调用的地方都可以 pinctrl_enet2是要使用的,必然会被调用.

pinctrl_enet2: enet2grp { fsl,pins = ; };

第三步添加PHY芯片的软复位驱动代码 软复位就是将LAN8720芯片中的复位寄存器设置 打开drivers/net/phy/phy.c b/drivers/net/phy/phy.c 这个是phy芯片的通用驱动 参考文章对drivers/net/phy/phy.c 的修改

烧录测试网卡

=> setenv eth1addr 00:01:3f:2d:3e:4d => setenv ipaddr 192.168.31.178 => setenv gatewayip 192.168.31.1 => setenv netmask 255.255.255.0 => setenv serverip 192.168.31.158 => saveenv => ping 192.168.31.158 ethernet@20b4000 Waiting for PHY auto negotiation to complete.... done Using ethernet@20b4000 device host 192.168.31.158 is alive


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有