Zynq-Linux移植学习笔记之十-u-boot网络配置
在zynq开发板zc706上,网络通路由下面三个设备组成:
其中zynq负责对phy进行配置,当zynq上的网络控制器以及phy完成正确配置时,能够看到RJ45上面的黄灯亮,此时表明链路已经通了。如果u-boot中已经设置了IP地址,通过网线就可以ping通电脑,此时会打印host alive这句话。
但是如果板子不是这样做的,比如是下面这种方式:
这里用到了BCM5396网络交换芯片,此时要保证网络链路通就需要对5396和两个PHY进行配置。幸运地是,PHY0由5396进行配置,当我们对5396进行正确配置后,PHY0也就配置完成了,PHY1的配置还是老样子。整个配置可以分为两步走,首先通过SPI总线配置5396,再配置PHY1,完成全部配置后,就能看到RJ45上面的黄灯亮起。
u-boot中需要修改的代码主要涉及三个地方
1、 arch/arm/lib/Board.c
其中board_init_r函数中需要在网络驱动配置前加入配置bcm5396的函数调用,这里我放在了串口驱动配置之后运行。
- void board_init_r(gd_t *id, ulong dest_addr)
- {
- ulong malloc_start;
- #if !defined(CONFIG_SYS_NO_FLASH)
- ulong flash_size;
- #endif
- gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
- bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
- monitor_flash_len = _end_ofs;
- /* Enable caches */
- enable_caches();
- debug("monitor flash len: %08lX\n", monitor_flash_len);
- board_init(); /* Setup chipselects */
- /*
- * TODO: printing of the clock inforamtion of the board is now
- * implemented as part of bdinfo command. Currently only support for
- * davinci SOC's is added. Remove this check once all the board
- * implement this.
- */
- #ifdef CONFIG_CLOCKS
- set_cpu_clk_info(); /* Setup clock information */
- #endif
- serial_initialize();
- myspi_init(); /*init bcm5396*/
- printf("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
- #ifdef CONFIG_LOGBUFFER
2、 net/Eth.c
在其中加入配置bcm5396的代码
- void myspi_init()
- {
- XSpiPs Spi;
- int i32Option,status;
- int i;
- unsigned char workBuf[10];
- workBuf[0]=0xf0;
- workBuf[1]=0x1;
- g_SpiConfig = &XSpiPs_ConfigTable[0];
- //Initialize the SPI device.
- Spi.IsBusy = 0;
- Spi.Config.BaseAddress = g_SpiConfig->BaseAddress;
- //Spi.StatusHandler = StubStatusHandler;
- Spi.SendBufferPtr = NULL;
- Spi.RecvBufferPtr = NULL;
- Spi.RequestedBytes = 0;
- Spi.RemainingBytes = 0;
- Spi.IsReady = 0x11111111;
- XSpiPs_WriteReg(Spi.Config.BaseAddress,0,0x00020000);
- //Initialize the SPI device. end
- i32Option = 0x1 | 0x2 | 0x4 | 0x10;
- Spi_SetOptions(&Spi, i32Option);
- XSpiPs_SetSlaveSelect(&Spi,1 );
- XSpiPs_SetClkPrescaler(&Spi, 6 );
- workBuf[0]=0xf0;
- workBuf[1]=0x1;
- workBuf[2]=0;
- for(i=0x10;i<=0x1f;i++)
- {
- status = writeBCM5396(&Spi, i, 0x20, workBuf );
- }
- printf("*****************Read SPI Reg of 5396******************\r\n");
- printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n");
- for(i=0x10;i<=0x1f;i++)
- {
- status = readBCM5396(&Spi, i, 0x28, workBuf );
- printf("port=%d,offset=0x28,data=0x%x\n",(i-0x10),workBuf[2]);
- printf("port=%d,offset=0x29,data=0x%x\n",(i-0x10),workBuf[3]);
- }
- printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n\r");
- for(i=0x10;i<=0x1f;i++)
- {
- status = readBCM5396(&Spi, i, 0x20, workBuf );
- printf("port=%d,offset=0x20,data=0x%x\n\r",(i-0x10),workBuf[2]);
- printf("port=%d,offset=0x21,data=0x%x\n\r",(i-0x10),workBuf[3]);
- }
- }
3、 drivers/net/Zynq_gem.c
这里的修改是可选项,主要是配置phy,我这里使用的是marvell的88E1111,u-boot中提供的配置方法不起效,于是进行了手动配置。加了phy_detect和negotiat函数
- static void phy_negotiat(struct eth_device *dev)
- {
- struct zynq_gem_priv *priv = dev->priv;
- u16 control;
- u16 status;
- u16 temp;
- u16 timeout_counter=0;
- printf("Start PHY autonegotiation.\n");
- phywrite(dev,priv->phyaddr, 22, 2);
- phyread(dev, priv->phyaddr, 21, &control);
- control |= 0x0030;
- phywrite(dev, priv->phyaddr, 21, control);
- phywrite(dev, priv->phyaddr, 22, 0);
- phyread(dev, priv->phyaddr, 4, &control);
- control |= 0x0800;
- control |= 0x0400;
- control |= (0x0100 | 0x0080);
- control |= (0x0040 | 0x0020);
- phywrite(dev, priv->phyaddr, 4, control);
- phyread(dev, priv->phyaddr, 9,&control);
- control |= 0x0300;
- phywrite(dev, priv->phyaddr, 9,control);
- phywrite(dev, priv->phyaddr, 22, 0);
- phyread(dev, priv->phyaddr, 16,&control);
- control |= (7 << 12); /* max number of gigabit attempts */
- control |= (1 << 11); /* enable downshift */
- phywrite(dev, priv->phyaddr, 16,control);
- phyread(dev, priv->phyaddr, 0, &control);
- control |= 0x1000;
- control |= 0x0200;
- phywrite(dev, priv->phyaddr, 0, control);
- phyread(dev, priv->phyaddr, 0, &control);
- control |= 0x8000;
- phywrite(dev, priv->phyaddr, 0, control);
- while (1)
- {
- phyread(dev, priv->phyaddr, 0, &control);
- if (control & 0x8000)
- {
- continue;
- }
- else
- {
- break;
- }
- }
- phyread(dev, priv->phyaddr, 1, &status);
- printf("Waiting for PHY to complete autonegotiation.\n");
- while ( !(status & 0x0020) )
- {
- phyread(dev, priv->phyaddr,19, &temp);
- // timeout_counter++;
- // if (timeout_counter == 30)
- // {
- // printf("Auto negotiation error\n");
- // return;
- // }
- phyread(dev, priv->phyaddr, 1, &status);
- }
- printf("autonegotiation complete.\n");
- }
- static void phy_detection(struct eth_device *dev)
- {
- int i;
- u16 phyreg;
- struct zynq_gem_priv *priv = dev->priv;
- if (priv->phyaddr != -1) {
- phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg);
- printf("phy reg is %d\n",phyreg);
- if ((phyreg != 0xFFFF) &&
- ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
- /* Found a valid PHY address */
- printf("Default phy address %d is valid\n",
- priv->phyaddr);
- return;
- } else {
- printf("PHY address is not setup correctly %d\n",
- priv->phyaddr);
- priv->phyaddr = -1;
- }
- }
- printf("detecting phy address\n");
- if (priv->phyaddr == -1) {
- /* detect the PHY address */
- for (i = 31; i >= 0; i--) {
- phyread(dev, i, PHY_DETECT_REG, &phyreg);
- if ((phyreg != 0xFFFF) &&
- ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
- /* Found a valid PHY address */
- priv->phyaddr = i;
- printf("Found valid phy address, %d\n", i);
- return;
- }
- }
- }
- priv->phyaddr = 0;
- printf("No PHY detected. Assuming a PHY at address 0\r\n");
- }
- static int zynq_gem_setup_mac(struct eth_device *dev)
- {
- u32 i, macaddrlow, macaddrhigh;
- struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
- /* Set the MAC bits [31:0] in BOT */
- macaddrlow = dev->enetaddr[0];
- macaddrlow |= dev->enetaddr[1] << 8;
- macaddrlow |= dev->enetaddr[2] << 16;
- macaddrlow |= dev->enetaddr[3] << 24;
- /* Set MAC bits [47:32] in TOP */
- macaddrhigh = dev->enetaddr[4];
- macaddrhigh |= dev->enetaddr[5] << 8;
- for (i = 0; i < 4; i++) {
- writel(0, ®s->laddr[i][LADDR_LOW]);
- writel(0, ®s->laddr[i][LADDR_HIGH]);
- /* Do not use MATCHx register */
- writel(0, ®s->match[i]);
- }
- writel(macaddrlow, ®s->laddr[0][LADDR_LOW]);
- writel(macaddrhigh, ®s->laddr[0][LADDR_HIGH]);
- return 0;
- }
- static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
- {
- u32 i;
- u16 tmp;
- unsigned long clk_rate = 0;
- struct phy_device *phydev;
- const u32 stat_size = (sizeof(struct zynq_gem_regs) -
- offsetof(struct zynq_gem_regs, stat)) / 4;
- struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
- struct zynq_gem_priv *priv = dev->priv;
- const u32 supported = SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full;
- if (!priv->init) {
- /* Disable all interrupts */
- writel(0xFFFFFFFF, ®s->idr);
- /* Disable the receiver & transmitter */
- writel(0, ®s->nwctrl);
- writel(0, ®s->txsr);
- writel(0, ®s->rxsr);
- writel(0, ®s->phymntnc);
- /* Clear the Hash registers for the mac address
- * pointed by AddressPtr
- */
- writel(0x0, ®s->hashl);
- /* Write bits [63:32] in TOP */
- writel(0x0, ®s->hashh);
- /* Clear all counters */
- for (i = 0; i <= stat_size; i++)
- readl(®s->stat[i]);
- /* Setup RxBD space */
- memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd));
- for (i = 0; i < RX_BUF; i++) {
- priv->rx_bd[i].status = 0xF0000000;
- priv->rx_bd[i].addr =
- ((u32)(priv->rxbuffers) +
- (i * PKTSIZE_ALIGN));
- }
- /* WRAP bit to last BD */
- priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK;
- /* Write RxBDs to IP */
- writel((u32)priv->rx_bd, ®s->rxqbase);
- /* Setup for DMA Configuration register */
- writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr);
- /* Setup for Network Control register, MDIO, Rx and Tx enable */
- setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK);
- priv->init++;
- }
- printf("phy detection.\n");
- phy_detection(dev);
- phy_rst(dev);
- phy_negotiat(dev);
- printf("--------phyaddr : 0x%x----\r\n", priv->phyaddr);
- unsigned short PhyReg;
- //change to page 0
- phyread(dev, priv->phyaddr, 22, &PhyReg);
- PhyReg = PhyReg & 0xfffe;
- phywrite(dev, priv->phyaddr, 22, PhyReg);
- phyread(dev, priv->phyaddr, 20, &PhyReg);
- PhyReg = PhyReg | 0x82;
- phywrite(dev, priv->phyaddr, 20, PhyReg);
- /* reset phy */
- phyread(dev, priv->phyaddr, 0, &PhyReg);
- PhyReg |= 0x8000;
- phywrite(dev, priv->phyaddr, 0, PhyReg);
- puts("GEM link speed is 1000Mbps\n");
- writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, ®s->nwcfg);
- setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
- ZYNQ_GEM_NWCTRL_TXEN_MASK);
- return 0;
- }
完成这三个地方配置后,重新编译u-boot,网络才算完成,可以通过tftp加载devicetree,uramdisk.image.gz,uImage,这样要比通过JTAG dow到内存中快很多,最后通过bootm启动就可以了。
- zynq-uboot> tftp 0x2a00000 devicetree.dtb
- Using zynq_gem device
- TFTP from server 192.168.0.101; our IP address is 192.168.0.99
- Filename 'devicetree.dtb'.
- Load address: 0x2a00000
- Loading: T #
- done
- Bytes transferred = 13222 (33a6 hex)
- zynq-uboot> tftp 0x2000000 uramdisk.image.gz
- Using zynq_gem device
- TFTP from server 192.168.0.101; our IP address is 192.168.0.99
- Filename 'uramdisk.image.gz'.
- Load address: 0x2000000
- Loading: #################################################################
- #################################################################
- #################################################################
- #################################################################
- #################################################################
- ####################################
- done
- Bytes transferred = 5289509 (50b625 hex)
- zynq-uboot> tftp 0x3000000 uImage
- Using zynq_gem device
- TFTP from server 192.168.0.101; our IP address is 192.168.0.99
- Filename 'uImage'.
- Load address: 0x3000000
- Loading: T #################################################################
- #################################################################
- #################################################################
- ##########################
- done
- Bytes transferred = 3230680 (314bd8 hex)
- zynq-uboot> bootm 0x3000000 0x2000000 0x2a00000
- ## Booting kernel from Legacy Image at 03000000 ...
- Image Name: Linux-4.0.0-dayun
- Image Type: ARM Linux Kernel Image (uncompressed)
- Data Size: 3230616 Bytes = 3.1 MiB
- Load Address: 00008000
- Entry Point: 00008000
- Verifying Checksum ... OK
- ## Loading init Ramdisk from Legacy Image at 02000000 ...
- Image Name:
- Image Type: ARM Linux RAMDisk Image (gzip compressed)
- Data Size: 5289445 Bytes = 5 MiB
- Load Address: 00800000
- Entry Point: 00800000
- Verifying Checksum ... OK
- ## Flattened Device Tree blob at 02a00000
- Booting using the fdt blob at 0x02a00000
- Loading Kernel Image ... OK
- OK
- Loading Ramdisk to 1faf4000, end 1ffff5e5 ... OK
- Loading Device Tree to 1faed000, end 1faf33a5 ... OK
- Starting kernel ...
- Uncompressing Linux... done, booting the kernel.
- Booting Linux on physical CPU 0x0
- Linux version 4.0.0-dayun (root@shenvpc) (gcc version 5.2.1 20151005 (Linaro GCC 5.2-2015.11-2) ) #1 SMP PREEMPT Fri Apr 7 02:03:21 Local time zone must be set--s
- CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d
- CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
- .......
Zynq-Linux移植学习笔记之十-u-boot网络配置的更多相关文章
- linux学习笔记二:三种网络配置
本文引用自:https://www.linuxidc.com/Linux/2017-05/144370.htm [linux公社] VMware为我们提供了三种网络工作模式,它们分别是:Bridged ...
- Java学习笔记【十二、网络编程】
原计划的学习结束时间是3月4日,目前看来已经延迟了,距离低标还差一些,多方面原因,也不找借口,利用周末赶赶进度,争取本周末把低标完成吧! 参考: http://www.runoob.com/java/ ...
- python学习笔记(十八)网络编程之requests模块
上篇博客中我们使用python自带的urllib模块去请求一个网站,或者接口,但是urllib模块太麻烦了,传参数的话,都得是bytes类型,返回数据也是bytes类型,还得解码,想直接把返回结果拿出 ...
- struts2学习笔记之十四:使用注解配置Action(不是和spring集成使用)
Struts2支持使用注解配置Action,减少配置文件的配置 Struts2如果要支持注解配置Action,需要插件的支持,导入插件struts2-convention-plugin-2.1.8.1 ...
- 红帽学习笔记[RHCSA] 第七课[网络配置相关]
第七课[网络配置相关] 在Vmware中添加网卡 编辑 -> 编辑虚拟网络 -> 添加网络->随便选择一个如VMnet2-> 选择仅主机模式 -> 勾掉使用本地DHCP服 ...
- Linux系统学习笔记:文件I/O
Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...
- Binder学习笔记(十二)—— binder_transaction(...)都干了什么?
binder_open(...)都干了什么? 在回答binder_transaction(...)之前,还有一些基础设施要去探究,比如binder_open(...),binder_mmap(...) ...
- 深挖计算机基础:趣谈Linux操作系统学习笔记
参考极客时间专栏<趣谈Linux操作系统>学习笔记 核心原理篇:内存管理 趣谈Linux操作系统学习笔记:第二十讲 趣谈Linux操作系统学习笔记:第二十一讲 趣谈Linux操作系统学习笔 ...
- linux 驱动学习笔记01--Linux 内核的编译
由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...
随机推荐
- JS常用函数与方法
//当页面关闭时触发 window.onbeforeunload = function() { alert('关闭了吧'); } //关闭窗口(弹出式窗口) parent.window.close() ...
- Eclipse版GoogleI/O2014开源项目
https://github.com/google/iosched谷歌原版是Gradle工程,用Eclipse开发的导入不了,所以搞了一个Elicpse工程,依赖的jar.库比较多,也比较难找... ...
- Angular基础---->AngularJS的使用(一)
AngularJS主要用于构建单页面的Web应用.它通过增加开发人员和常见Web应用开发任务之间的抽象级别,使构建交互式的现代Web应用变得更加简单.今天,我们就开始Angular环境的搭建和第一个实 ...
- python的内存管理与垃圾回收机制学习
一.python内存申请: 1.python的内存管理分为六层:最底的两层有OS控制.第三层是调用C的malloc和free等进行内存控制.第四层第五层是python的内存池.最上层使我们接触的直接对 ...
- Navicat 创建 Mysql 函数
1.点击新建函数 2.写函数,保存为v1 3.调用 SELECT id,v1(id) from 表
- 【Android】android string.xml前后加空格的技巧
android string.xml 文字中间加入空格 <string name="password">密 码</string>   ...
- 微信小程序 --- 模板的使用
由于微信小程序文件大小的限制,可以把一些公用的文件 单离出来形成模板,从而被各个模板引用: 定义模板第一种方式: 新建一个目录: 写入: <text>hello world</tex ...
- onethink判断是否是手机访问?
第一步:找到:Application / Common / Common / function.php 添加判断是否是手机访问的代码: /** * 判断当前访问的用户是 PC端 还是 手机端 返回tr ...
- Dreamweaver 中CSS代码格式化
首先,用DW打开一个已经写好的css文件,看一下编辑好的,没有格式化之前的代码的样子. 然后,我们点击软件窗口上方的“命令”选项,在弹出的菜单中点击“应用源格式”选项,就可以将我们的代码格式化. ...
- SIFT算法的教程及源码
1.ubc:DAVID LOWE---SIFT算法的创始人,两篇巨经典经典的文章http://www.cs.ubc.ca/~lowe/[1] 2.cmu:YanKe---PCASIFT,总结的SIFT ...