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 添加js节点
function AddScriptNode(src) { var N = document.createElement("script"); N.setAttribute(&qu ...
- poj_3185 反转问题
题目大意 有20个碗排成一排,有些碗口朝上,有些碗口朝下.每次可以反转其中的一个碗,但是在反转该碗时,该碗左右两边的碗也跟着被反转(如果该碗为边界上的碗,则只有一侧的碗被反转).求最少需要反转几次,可 ...
- java高级---->Thread之CountDownLatch的使用
CountDownLatch是JDK 5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生.今天我们通过一些实例来学习一下它的用法. CountDownLatch的简单使用 CountDow ...
- tomcat源码---->request的请求参数分析
当contentType为application/json的时候,在servlet中通过request.getParameter得到的数据为空.今天我们就java的请求,分析一下request得到参数 ...
- window.postMessage跨文档通信
window.postMessage 1.浏览器兼容情况:IE8+.chrome.firefox等较新浏览器都至此. 2.使用方法: a.otherWindow.postMessage( messag ...
- select标签的onchange事件
/** @1.onchange事件 ==> select选择事件* @2.obj.options ==> 选择option集合* @3.obj.selectedIndex ==> 选 ...
- android选择图片或拍照图片上传到服务器(包括上传参数)
From:http://blog.csdn.net/springsky_/article/details/8213898具体上传代码: 1.选择图片和上传界面,包括上传完成和异常的回调监听 [java ...
- Feature Tools 简介
FeatureTools是2017年9月上线的github项目,是一个自动生成特征的工具,应用于关系型数据. github链接:https://github.com/Featuretools/feat ...
- github团队协作教程
跟着笔者魔鬼般的步伐,我们一起来瞅瞅一个团队协作的任务如何进行版本管理吧~ 要跟上哦~ =============================================== 首先我们先来看下 ...
- C++ Design Pattern: What is a Design Pattern?
Q: What is a Design Pattern? A: Design Patterns represent solutions to problems what arise when deve ...