在rk3328上从零构建ubuntu16.04系统系列(1):sdk的环境配置和编译与uboot的网卡驱动配置

7 篇文章 0 订阅
2 篇文章 1 订阅

   如果有问题,请加QQ群 891339868 进行交流

         当前的项目是基于RK3328的硬件方案,安装ubuntu16.04系统,现在基本上告一段落,现在将这个过程记录下来,以备以后查阅,今天先描述一下怎么解决uboot网卡驱动的问题。

    说是从零开始,其实是不可能的,所有的项目都是站在巨人的肩膀上做的一些小补丁,这个项目也不例外,我使用的是firefly提供的开发板和他们的sdk,写到这里,不得不由衷的称赞一下firefly,他们是国内为数不多的无偿提供sdk的厂家,不管你买不买他们的板子,所有的sdk都可以在他们的官网上下载,这一点做的无可挑剔,好了,废话少说,步入正题:

一、下载firefly提供的rk3328的sdk,对于老版本的sdk,其实都是一样的,下载下来后更新一下就醒了,新版本的不需要,我下载的是firefly-sdk-20200629.7z这个版本,需要根据以下步骤进行处理,其实都是些程式化的操作,没有什么复杂度:

1、下载firefly-sdk-20200629.7z这个文件包

2、下载common-linux-bundle这个更新包

以上这两个包原来在firefly的官网上都是能下载下来的,现在资源更新了,可能只能下载新的sdk了,不过只是这些东西不一样,接下来的本质上的东西还是一样的

3、根据下列命令解压并更新sdk

7z x firefly-sdk-20200629.7z 
cd firefly-sdk
git reset --hard
//下边是更新远程仓库,有时候会出错,或者时间很久,多试几次
git clone https://github.com/FireflyTeam/bundle.git -b rk3328-linux-bundle

./bundle/update rk3328-linux-bundle
git rebase FETCH_HEAD

//再把之前下载的common-linux-bundle更新包放到 firefly-sdk主目录
mv common-linux-bundle/ .common-linux-bundle/
chmod 755 .common-linux-bundle/update && .common-linux-bundle/update
git rebase FETCH_HEAD

4、配置编译环境

sudo apt-get install git gcc-arm-linux-gnueabihf u-boot-tools device-tree-compiler mtools \
parted libudev-dev libusb-1.0-0-dev python-linaro-image-tools linaro-image-tools libssl-dev \
autotools-dev libsigsegv2 m4 libdrm-dev curl sed make binutils build-essential gcc g++ bash \
patch gzip bzip2 perl tar cpio python unzip rsync file bc wget libncurses5 libglib2.0-dev \
openssh-client lib32stdc++6 gcc-aarch64-linux-gnu libncurses5-dev lzop libssl1.0.0 libssl-dev

操作到这里,开发环境就搭建完成。

二、修改并编译sdk里面的uboot

firefly提供的sdk里面的uboot是不支持网络的,但是在实际的开发过程中,uboot通过tftp加载kernel和设备树是比较常见的开发方式,所以,uboot支持网络其实是一个刚需,下面就看一下那些地方需要修改和配置,其实可以参考我的另外一篇文章,rk3308b使用tftp启动内核和设备树,使用nfs文件系统,并且安装ubuntu16.04(一):rk3308b使用tftp启动内核和设备树,使用nfs文件系统,并且安装ubuntu16.04(一)_b7376811的博客-CSDN博客
1、使能uboot的驱动模型,具体的路径为Device Drivers  --->[*] Enable Driver Model for Ethernet drivers:

2、使能rk3328的mac驱动,具体的路径为:Device Drivers  --->[*] Network device support  --->[*]   Rockchip Synopsys Designware Ethernet MAC:

3、使能rk3328的phy驱动,具体的路径为:Device Drivers  --->-*- Ethernet PHY (physical media interface) support  --->[*]   Realtek Ethernet PHYs support:

4、使能产生随机mac地址,要不然网卡不能使用,具体的路径为-*- Networking support  ---> [*]   Random ethaddr if unset:

5、 接着要修改环境变量的存储方式,我这里使用的是EMMC,所以要设置为MMC,要不然设置的ip地址不能保存,具体的路径为Environment  --->Select the location of the environment (Environment in an MMC device)  ---> (X) Environment in an MMC device:

以上这几步其实和rk3308b的差别不大。

6、先查看一下uboot里面默认配置的设备树是哪一个,最后根据电路图修改uboot的设备树里面关于网口的描述,如下图所示:

 从图中可以看到,默认配置的是rk3328-firefly.dts,在uboot/arch/arm/dts/路径下寻找相关设备树文件,如下图所示:

 一查,果然有(废话),打开这个文件,寻找和网卡相关的配置,和mac相关的配置有下面几项:

//时钟相关的配置
gmac_clkin: external-gmac-clock {
		compatible = "fixed-clock";
		clock-frequency = <25000000>;
		clock-output-names = "gmac_clkin";
		#clock-cells = <0>;
	};

//和gpio相关的配置
&gmac2io {
	phy-suplly = <&vcc_phy>;
	phy-mode = "rmii";
	clock_in_out = "output";
	//snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
	snps,reset-active-low;
	snps,force_thresh_dma_mode;
	snps,reset-delay-us = <0 30000 50000>;
	//assigned-clocks = <&cru SCLK_MAC2IO_REFOUT>;
	assigned-clocks = <&cru SCLK_MAC2IO>;
	assigned-clock-parents = <&gmac_clkin>;
	pinctrl-names = "default";
	pinctrl-0 = <&rmiim1_pins &gmac_reset>;
	//pinctrl-0 = <&gmac_reset>;
	tx_delay = <0x28>;
	rx_delay = <0x16>;
	status = "okay";
};

//和内置phy相关的配置,我们用的是外置phy,所以不需要考虑
gmac2phy {
		gmac_reset: gmac-reset {
			rockchip,pins = 
				<RK_GPIO1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};

从上面的代码可以卡的出来,这个文件引用了前面文件名称为gmac2iolabel,所以,要向上扒拉扒拉,看看倒地是哪个文件里面定义的这个label,根据该文件引用的头文件,很容易找到是rk3328.dtsi这个文件,在这个文件里面找到gmac2io这个label,如下面的代码所示:
 

gmac2io: ethernet@ff540000 {
		compatible = "rockchip,rk3328-gmac";
		reg = <0x0 0xff540000 0x0 0x10000>;
		rockchip,grf = <&grf>;
		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
		interrupt-names = "macirq";
		clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_RX>,
			 <&cru SCLK_MAC2IO_TX>, <&cru SCLK_MAC2IO_REF>,
			 <&cru SCLK_MAC2IO_REFOUT>, <&cru ACLK_MAC2IO>,
			 <&cru PCLK_MAC2IO>;
		clock-names = "stmmaceth", "mac_clk_rx",
			      "mac_clk_tx", "clk_mac_ref",
			      "clk_mac_refout", "aclk_mac",
			      "pclk_mac";
		resets = <&cru SRST_GMAC2IO_A>;
		reset-names = "stmmaceth";
		status = "disabled";
	};

修改过设备树后,要禁止uboot使用kernel设备树,在RK的sdk里面,为了提高uboot的兼容性,bootloader的第二阶段,默认使用了kernel的设备树,这样的话就可以实现一种uboot配置,可以适配同一型号芯片的多种板卡,提高uboot的兼容性。我在这里禁止了这一功能,以上的设备树配置就可以生效了,具体的配置路径为:ARM architecture  --->[ ] Using dtb from Kernel/resource for U-Boot

正常情况下,在设备树里面使能这几项就可以驱动网卡,可是事与愿违,配置设备树以后,网卡依然不能用,那就应该是驱动的问题了。 

从上面的两段代码里面可以得出以下结论:

(1)、uboot的驱动中需要匹配两大块儿内容,一个是时钟相关的驱动,一个是gmac2io相关的驱动;

(2)、时钟相关的驱动通过“rockchip,rk3328-cru”字段去匹配,gmac2io相关的驱动通过“rockchip,rk3328-gmac”字段去匹配;

首先去研究和时钟相关的驱动,直接在uboot源码中搜索“rockchip,rk3328-cru”字段,很幸运,很快就找到了,为什么说是很幸运呢?是因为如果找不到,那就要从头写这个驱动了,具体代码如下面所示:

static void rkclk_init(struct rk3328_clk_priv *priv)
{
    其他代码省略
	.................................................................
    rk_clrsetreg(&priv->cru->clksel_con[24], (0x3f << 8) | (0x3f << 0),
		     (0x17 << 8) | (0x17 << 0));

	#if 1
	rk_clrsetreg(&priv->cru->clksel_con[25], (0xff << 8) | (0xff << 0),
		     (0x00 << 8) | (0x00 << 0));
	//printf("clksel_con[25]' val is 0x%x \n", priv->cru->clksel_con[25]);
	rk_clrsetreg(&priv->cru->clksel_con[25], (0x1f << 8) | (0x1f << 0),
		     (0x02 << 8) | (0x07 << 0));
	#endif

    rk_clrsetreg(&priv->cru->clksel_con[27], (0x1f << 8) | (0x1f << 0),
		     (0x17 << 8) | (0x17 << 0));
......................................................................
其他代码省略
}

......................代码太长了,无关的代码省略

static const struct udevice_id rk3328_clk_ids[] = {
	{ .compatible = "rockchip,rk3328-cru" },
	{ }
};

U_BOOT_DRIVER(rockchip_rk3328_cru) = {
	.name		= "rockchip_rk3328_cru",
	.id		= UCLASS_CLK,
	.of_match	= rk3328_clk_ids,
	.priv_auto_alloc_size = sizeof(struct rk3328_clk_priv),
	.ofdata_to_platdata = rk3328_clk_ofdata_to_platdata,
	.ops		= &rk3328_clk_ops,
	.bind		= rk3328_clk_bind,
	.probe		= rk3328_clk_probe,
};
................................

代码太长了,无关代码省略,只有一个地方需要修改,就是static void rkclk_init(struct rk3328_clk_priv *priv)函数中,在设置CRU_CLKSEL_CON24CRU_CLKSEL_CON27之间添加对CRU_CLKSEL_CON25的初始化,具体的流程如下:

首先CRU_CLKSEL_CON25所有bit清零;

其次CRU_CLKSEL_CON25的bit9设置为1,bit2-0设置为111;

到此,时钟相关的配置就算完成了,寄存器相关的描述如下图所示:

 

        接着分析gmac2io相关的代码上,使用“rockchip,rk3328-gmac”字段去源码中搜索,很快,找到相关代码,具体的路径为:uboot/driver/net/gmac_rockchip.c这个文件里面,从这个驱动中可以看出,它兼容rockchip很多平台,把和rk3328相关的代码摘出来看一看:

说明:下面这段代码是我自己增加的代码
static void rk3328_gmac_set_to_rmii(struct gmac_rockchip_platdata *pdata)
{
	//printf("rk3328_gmac_set_to_rmii! \n");
	struct rk3328_grf_regs *grf;
	enum {
		RK3328_RMII_MODE_MASK  = BIT(9),
		RK3328_GMAC_PHY_INTF_SEL_MASK  = GENMASK(6, 4),
		RK3328_GMAC_PHY_INTF_SEL_RMII  = BIT(6),
		RK3328_GMAC_CLK_SRC_SEL_MASK = BIT(10),
		RK3328_GMAC_CLK_SRC_SEL_CRU = 0,
		RK3328_GMAC_TO_IO_SPEED_MASK = BIT(2),
		RK3328_GMAC_TO_IO_SPEED_100M = BIT(2),//�������ã�Ҫ��Ȼ���粻ͨ
	};

	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
	//printf("grf->mac_con[1] is %u \n", grf->mac_con[1]);
	rk_clrsetreg(&grf->mac_con[1],
			RK3328_RMII_MODE_MASK |
		    RK3328_GMAC_PHY_INTF_SEL_MASK |
			RK3328_GMAC_CLK_SRC_SEL_MASK |
			RK3328_GMAC_TO_IO_SPEED_MASK, 
			RK3328_GMAC_PHY_INTF_SEL_RMII | 
			RK3328_RMII_MODE_MASK |
			RK3328_GMAC_CLK_SRC_SEL_CRU |
			RK3328_GMAC_TO_IO_SPEED_100M);

	//printf("grf->mac_con[1] is %u \n", grf->mac_con[1]);
}

static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv)
{
	//printf("rk3328_gmac_fix_mac_speed! \n");
	struct rk3328_grf_regs *grf;
	int clk;
	enum {
		RK3328_GMAC_CLK_SEL_MASK  = BIT(7),
		RK3328_GMAC_CLK_SEL_25M   = 1 << 7,
		RK3328_GMAC_CLK_SEL_2_5M  = 0 << 7,
	};

	//printf("priv->phydev-speed is %d \n", priv->phydev->speed);

	switch (priv->phydev->speed) {
	case 10:
		clk = RK3328_GMAC_CLK_SEL_2_5M;
		break;
	case 100:
		clk = RK3328_GMAC_CLK_SEL_25M;
		break;
	default:
		debug("Unknown phy speed: %d\n", priv->phydev->speed);
		return -EINVAL;
	}

	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
	rk_clrsetreg(&grf->mac_con[1], RK3328_GMAC_CLK_SEL_MASK, clk);

	return 0;
}

const struct rk_gmac_ops rk3328_gmac_ops = {
	.fix_mac_speed = rk3328_gmac_fix_mac_speed,
	//.set_to_rgmii = rk3328_gmac_set_to_rgmii,//uboot默认的代码
	.set_to_rmii = rk3328_gmac_set_to_rmii,//我增加的代码
};


static const struct udevice_id rockchip_gmac_ids[] = {
	{ .compatible = "rockchip,px30-gmac",
	  .data = (ulong)&px30_gmac_ops },
	{ .compatible = "rockchip,rk1808-gmac",
	  .data = (ulong)&rk1808_gmac_ops },
	{ .compatible = "rockchip,rk3228-gmac",
	  .data = (ulong)&rk3228_gmac_ops },
	{ .compatible = "rockchip,rk3288-gmac",
	  .data = (ulong)&rk3288_gmac_ops },
	{ .compatible = "rockchip,rk3308-mac",
	  .data = (ulong)&rk3308_gmac_ops },
	{ .compatible = "rockchip,rk3328-gmac",
	  .data = (ulong)&rk3328_gmac_ops },
	{ .compatible = "rockchip,rk3368-gmac",
	  .data = (ulong)&rk3368_gmac_ops },
	{ .compatible = "rockchip,rk3399-gmac",
	  .data = (ulong)&rk3399_gmac_ops },
	{ .compatible = "rockchip,rv1108-gmac",
	  .data = (ulong)&rv1108_gmac_ops },
	{ }
};

U_BOOT_DRIVER(eth_gmac_rockchip) = {
	.name	= "gmac_rockchip",
	.id	= UCLASS_ETH,
	.of_match = rockchip_gmac_ids,
	.ofdata_to_platdata = gmac_rockchip_ofdata_to_platdata,
	.probe	= gmac_rockchip_probe,
	.ops	= &gmac_rockchip_eth_ops,
	.priv_auto_alloc_size = sizeof(struct dw_eth_dev),
	.platdata_auto_alloc_size = sizeof(struct gmac_rockchip_platdata),
	.flags = DM_FLAG_ALLOC_PRIV_DMA,
};

从代码上面不难看出,其实核心工作就是对rk3328的GRF_MAC_CON1寄存器进行配置,查看RK3328的TRM手册,手册可以在这个地址下载到:RK3328 - Rockchip open source Document

查看该寄存器的相关描述:

函数static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv)是对mac的时钟速率的设置,根据驱动从设备获取到的私有数据,来对GRF_MAC_CON1寄存器的bit7进行配置,0表示输入的时钟是2.5M,1表示输入的时钟是25M。

函数static void rk3328_gmac_set_to_rmii(struct gmac_rockchip_platdata *pdata)是对mac与phy的通信接口RMII的相关配置,主要是对GRF_MAC_CON1寄存器的bit9,bit6-4,bit10,bit2进行设置,下面详细说明一下:

bit9:设置为1,mac与phy的接口模式是RMII(注意:这个地方应该配合GRF_MAC_CON2进行配置,默认的CON2寄存器bit9是1,所以两个寄存器配置起来是11);

bit6-4:设置为100,设置phy的相关接口是RMII;

bit10:设置为0,设置为内部时钟模式,时钟是从cpu产生给mac,mac再把时钟给phy,所以当前模式下,phy不需要外接晶振;

bit2:设置为1,设置网络速率为100M;

其他bit默认就可以了,和net相关的配置就算完成了。

配置到这里,uboot的网卡就可以工作了,在uboot的启动以后,配置serverip和ipaddr,就可以使用网络了。

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值