在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的函数调用,这里我放在了串口驱动配置之后运行。

  1. void board_init_r(gd_t *id, ulong dest_addr)
  2. {
  3. ulong malloc_start;
  4. #if !defined(CONFIG_SYS_NO_FLASH)
  5. ulong flash_size;
  6. #endif
  7. gd->flags |= GD_FLG_RELOC;   /* tell others: relocation done */
  8. bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
  9. monitor_flash_len = _end_ofs;
  10. /* Enable caches */
  11. enable_caches();
  12. debug("monitor flash len: %08lX\n", monitor_flash_len);
  13. board_init();   /* Setup chipselects */
  14. /*
  15. * TODO: printing of the clock inforamtion of the board is now
  16. * implemented as part of bdinfo command. Currently only support for
  17. * davinci SOC's is added. Remove this check once all the board
  18. * implement this.
  19. */
  20. #ifdef CONFIG_CLOCKS
  21. set_cpu_clk_info(); /* Setup clock information */
  22. #endif
  23. serial_initialize();
  24. myspi_init(); /*init bcm5396*/
  25. printf("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
  26. #ifdef CONFIG_LOGBUFFER

2、  net/Eth.c

在其中加入配置bcm5396的代码

  1. void myspi_init()
  2. {
  3. XSpiPs Spi;
  4. int i32Option,status;
  5. int i;
  6. unsigned char workBuf[10];
  7. workBuf[0]=0xf0;
  8. workBuf[1]=0x1;
  9. g_SpiConfig = &XSpiPs_ConfigTable[0];
  10. //Initialize the SPI device.
  11. Spi.IsBusy = 0;
  12. Spi.Config.BaseAddress = g_SpiConfig->BaseAddress;
  13. //Spi.StatusHandler = StubStatusHandler;
  14. Spi.SendBufferPtr = NULL;
  15. Spi.RecvBufferPtr = NULL;
  16. Spi.RequestedBytes = 0;
  17. Spi.RemainingBytes = 0;
  18. Spi.IsReady = 0x11111111;
  19. XSpiPs_WriteReg(Spi.Config.BaseAddress,0,0x00020000);
  20. //Initialize the SPI device. end
  21. i32Option = 0x1 | 0x2 | 0x4 | 0x10;
  22. Spi_SetOptions(&Spi, i32Option);
  23. XSpiPs_SetSlaveSelect(&Spi,1 );
  24. XSpiPs_SetClkPrescaler(&Spi, 6 );
  25. workBuf[0]=0xf0;
  26. workBuf[1]=0x1;
  27. workBuf[2]=0;
  28. for(i=0x10;i<=0x1f;i++)
  29. {
  30. status = writeBCM5396(&Spi, i, 0x20, workBuf );
  31. }
  32. printf("*****************Read SPI Reg of 5396******************\r\n");
  33. printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n");
  34. for(i=0x10;i<=0x1f;i++)
  35. {
  36. status = readBCM5396(&Spi, i, 0x28, workBuf );
  37. printf("port=%d,offset=0x28,data=0x%x\n",(i-0x10),workBuf[2]);
  38. printf("port=%d,offset=0x29,data=0x%x\n",(i-0x10),workBuf[3]);
  39. }
  40. printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n\r");
  41. for(i=0x10;i<=0x1f;i++)
  42. {
  43. status = readBCM5396(&Spi, i, 0x20, workBuf );
  44. printf("port=%d,offset=0x20,data=0x%x\n\r",(i-0x10),workBuf[2]);
  45. printf("port=%d,offset=0x21,data=0x%x\n\r",(i-0x10),workBuf[3]);
  46. }
  47. }

3、  drivers/net/Zynq_gem.c

这里的修改是可选项,主要是配置phy,我这里使用的是marvell的88E1111,u-boot中提供的配置方法不起效,于是进行了手动配置。加了phy_detect和negotiat函数

  1. static void phy_negotiat(struct eth_device *dev)
  2. {
  3. struct zynq_gem_priv *priv = dev->priv;
  4. u16 control;
  5. u16 status;
  6. u16 temp;
  7. u16 timeout_counter=0;
  8. printf("Start PHY autonegotiation.\n");
  9. phywrite(dev,priv->phyaddr, 22, 2);
  10. phyread(dev, priv->phyaddr, 21, &control);
  11. control |= 0x0030;
  12. phywrite(dev, priv->phyaddr, 21, control);
  13. phywrite(dev, priv->phyaddr, 22, 0);
  14. phyread(dev, priv->phyaddr, 4, &control);
  15. control |= 0x0800;
  16. control |= 0x0400;
  17. control |= (0x0100 | 0x0080);
  18. control |= (0x0040 | 0x0020);
  19. phywrite(dev, priv->phyaddr, 4, control);
  20. phyread(dev, priv->phyaddr, 9,&control);
  21. control |= 0x0300;
  22. phywrite(dev, priv->phyaddr, 9,control);
  23. phywrite(dev, priv->phyaddr, 22, 0);
  24. phyread(dev, priv->phyaddr, 16,&control);
  25. control |= (7 << 12); /* max number of gigabit attempts */
  26. control |= (1 << 11); /* enable downshift */
  27. phywrite(dev, priv->phyaddr, 16,control);
  28. phyread(dev, priv->phyaddr, 0, &control);
  29. control |= 0x1000;
  30. control |= 0x0200;
  31. phywrite(dev, priv->phyaddr, 0, control);
  32. phyread(dev, priv->phyaddr, 0, &control);
  33. control |= 0x8000;
  34. phywrite(dev, priv->phyaddr, 0, control);
  35. while (1)
  36. {
  37. phyread(dev, priv->phyaddr, 0, &control);
  38. if (control & 0x8000)
  39. {
  40. continue;
  41. }
  42. else
  43. {
  44. break;
  45. }
  46. }
  47. phyread(dev, priv->phyaddr, 1, &status);
  48. printf("Waiting for PHY to complete autonegotiation.\n");
  49. while ( !(status & 0x0020) )
  50. {
  51. phyread(dev, priv->phyaddr,19,  &temp);
  52. //      timeout_counter++;
  53. //      if (timeout_counter == 30)
  54. //      {
  55. //          printf("Auto negotiation error\n");
  56. //          return;
  57. //      }
  58. phyread(dev, priv->phyaddr, 1, &status);
  59. }
  60. printf("autonegotiation complete.\n");
  61. }
  62. static void phy_detection(struct eth_device *dev)
  63. {
  64. int i;
  65. u16 phyreg;
  66. struct zynq_gem_priv *priv = dev->priv;
  67. if (priv->phyaddr != -1) {
  68. phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg);
  69. printf("phy reg is %d\n",phyreg);
  70. if ((phyreg != 0xFFFF) &&
  71. ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
  72. /* Found a valid PHY address */
  73. printf("Default phy address %d is valid\n",
  74. priv->phyaddr);
  75. return;
  76. } else {
  77. printf("PHY address is not setup correctly %d\n",
  78. priv->phyaddr);
  79. priv->phyaddr = -1;
  80. }
  81. }
  82. printf("detecting phy address\n");
  83. if (priv->phyaddr == -1) {
  84. /* detect the PHY address */
  85. for (i = 31; i >= 0; i--) {
  86. phyread(dev, i, PHY_DETECT_REG, &phyreg);
  87. if ((phyreg != 0xFFFF) &&
  88. ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
  89. /* Found a valid PHY address */
  90. priv->phyaddr = i;
  91. printf("Found valid phy address, %d\n", i);
  92. return;
  93. }
  94. }
  95. }
  96. priv->phyaddr = 0;
  97. printf("No PHY detected.  Assuming a PHY at address 0\r\n");
  98. }
  99. static int zynq_gem_setup_mac(struct eth_device *dev)
  100. {
  101. u32 i, macaddrlow, macaddrhigh;
  102. struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
  103. /* Set the MAC bits [31:0] in BOT */
  104. macaddrlow = dev->enetaddr[0];
  105. macaddrlow |= dev->enetaddr[1] << 8;
  106. macaddrlow |= dev->enetaddr[2] << 16;
  107. macaddrlow |= dev->enetaddr[3] << 24;
  108. /* Set MAC bits [47:32] in TOP */
  109. macaddrhigh = dev->enetaddr[4];
  110. macaddrhigh |= dev->enetaddr[5] << 8;
  111. for (i = 0; i < 4; i++) {
  112. writel(0, &regs->laddr[i][LADDR_LOW]);
  113. writel(0, &regs->laddr[i][LADDR_HIGH]);
  114. /* Do not use MATCHx register */
  115. writel(0, &regs->match[i]);
  116. }
  117. writel(macaddrlow, &regs->laddr[0][LADDR_LOW]);
  118. writel(macaddrhigh, &regs->laddr[0][LADDR_HIGH]);
  119. return 0;
  120. }
  121. static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
  122. {
  123. u32 i;
  124. u16 tmp;
  125. unsigned long clk_rate = 0;
  126. struct phy_device *phydev;
  127. const u32 stat_size = (sizeof(struct zynq_gem_regs) -
  128. offsetof(struct zynq_gem_regs, stat)) / 4;
  129. struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
  130. struct zynq_gem_priv *priv = dev->priv;
  131. const u32 supported = SUPPORTED_10baseT_Half |
  132. SUPPORTED_10baseT_Full |
  133. SUPPORTED_100baseT_Half |
  134. SUPPORTED_100baseT_Full |
  135. SUPPORTED_1000baseT_Half |
  136. SUPPORTED_1000baseT_Full;
  137. if (!priv->init) {
  138. /* Disable all interrupts */
  139. writel(0xFFFFFFFF, &regs->idr);
  140. /* Disable the receiver & transmitter */
  141. writel(0, &regs->nwctrl);
  142. writel(0, &regs->txsr);
  143. writel(0, &regs->rxsr);
  144. writel(0, &regs->phymntnc);
  145. /* Clear the Hash registers for the mac address
  146. * pointed by AddressPtr
  147. */
  148. writel(0x0, &regs->hashl);
  149. /* Write bits [63:32] in TOP */
  150. writel(0x0, &regs->hashh);
  151. /* Clear all counters */
  152. for (i = 0; i <= stat_size; i++)
  153. readl(&regs->stat[i]);
  154. /* Setup RxBD space */
  155. memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd));
  156. for (i = 0; i < RX_BUF; i++) {
  157. priv->rx_bd[i].status = 0xF0000000;
  158. priv->rx_bd[i].addr =
  159. ((u32)(priv->rxbuffers) +
  160. (i * PKTSIZE_ALIGN));
  161. }
  162. /* WRAP bit to last BD */
  163. priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK;
  164. /* Write RxBDs to IP */
  165. writel((u32)priv->rx_bd, &regs->rxqbase);
  166. /* Setup for DMA Configuration register */
  167. writel(ZYNQ_GEM_DMACR_INIT, &regs->dmacr);
  168. /* Setup for Network Control register, MDIO, Rx and Tx enable */
  169. setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK);
  170. priv->init++;
  171. }
  172. printf("phy detection.\n");
  173. phy_detection(dev);
  174. phy_rst(dev);
  175. phy_negotiat(dev);
  176. printf("--------phyaddr : 0x%x----\r\n", priv->phyaddr);
  177. unsigned short PhyReg;
  178. //change to page 0
  179. phyread(dev, priv->phyaddr, 22, &PhyReg);
  180. PhyReg = PhyReg & 0xfffe;
  181. phywrite(dev, priv->phyaddr, 22, PhyReg);
  182. phyread(dev, priv->phyaddr, 20, &PhyReg);
  183. PhyReg = PhyReg | 0x82;
  184. phywrite(dev, priv->phyaddr, 20, PhyReg);
  185. /*  reset phy    */
  186. phyread(dev, priv->phyaddr, 0, &PhyReg);
  187. PhyReg |= 0x8000;
  188. phywrite(dev, priv->phyaddr, 0, PhyReg);
  189. puts("GEM link speed is 1000Mbps\n");
  190. writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, &regs->nwcfg);
  191. setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
  192. ZYNQ_GEM_NWCTRL_TXEN_MASK);
  193. return 0;
  194. }

完成这三个地方配置后,重新编译u-boot,网络才算完成,可以通过tftp加载devicetree,uramdisk.image.gz,uImage,这样要比通过JTAG dow到内存中快很多,最后通过bootm启动就可以了。

    1. zynq-uboot> tftp 0x2a00000 devicetree.dtb
    2. Using zynq_gem device
    3. TFTP from server 192.168.0.101; our IP address is 192.168.0.99
    4. Filename 'devicetree.dtb'.
    5. Load address: 0x2a00000
    6. Loading: T #
    7. done
    8. Bytes transferred = 13222 (33a6 hex)
    9. zynq-uboot> tftp 0x2000000 uramdisk.image.gz
    10. Using zynq_gem device
    11. TFTP from server 192.168.0.101; our IP address is 192.168.0.99
    12. Filename 'uramdisk.image.gz'.
    13. Load address: 0x2000000
    14. Loading: #################################################################
    15. #################################################################
    16. #################################################################
    17. #################################################################
    18. #################################################################
    19. ####################################
    20. done
    21. Bytes transferred = 5289509 (50b625 hex)
    22. zynq-uboot> tftp 0x3000000 uImage
    23. Using zynq_gem device
    24. TFTP from server 192.168.0.101; our IP address is 192.168.0.99
    25. Filename 'uImage'.
    26. Load address: 0x3000000
    27. Loading: T #################################################################
    28. #################################################################
    29. #################################################################
    30. ##########################
    31. done
    32. Bytes transferred = 3230680 (314bd8 hex)
    33. zynq-uboot> bootm 0x3000000 0x2000000 0x2a00000
    34. ## Booting kernel from Legacy Image at 03000000 ...
    35. Image Name:   Linux-4.0.0-dayun
    36. Image Type:   ARM Linux Kernel Image (uncompressed)
    37. Data Size:    3230616 Bytes = 3.1 MiB
    38. Load Address: 00008000
    39. Entry Point:  00008000
    40. Verifying Checksum ... OK
    41. ## Loading init Ramdisk from Legacy Image at 02000000 ...
    42. Image Name:
    43. Image Type:   ARM Linux RAMDisk Image (gzip compressed)
    44. Data Size:    5289445 Bytes = 5 MiB
    45. Load Address: 00800000
    46. Entry Point:  00800000
    47. Verifying Checksum ... OK
    48. ## Flattened Device Tree blob at 02a00000
    49. Booting using the fdt blob at 0x02a00000
    50. Loading Kernel Image ... OK
    51. OK
    52. Loading Ramdisk to 1faf4000, end 1ffff5e5 ... OK
    53. Loading Device Tree to 1faed000, end 1faf33a5 ... OK
    54. Starting kernel ...
    55. Uncompressing Linux... done, booting the kernel.
    56. Booting Linux on physical CPU 0x0
    57. 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
    58. CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d
    59. CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
    60. .......

Zynq-Linux移植学习笔记之十-u-boot网络配置的更多相关文章

  1. linux学习笔记二:三种网络配置

    本文引用自:https://www.linuxidc.com/Linux/2017-05/144370.htm [linux公社] VMware为我们提供了三种网络工作模式,它们分别是:Bridged ...

  2. Java学习笔记【十二、网络编程】

    原计划的学习结束时间是3月4日,目前看来已经延迟了,距离低标还差一些,多方面原因,也不找借口,利用周末赶赶进度,争取本周末把低标完成吧! 参考: http://www.runoob.com/java/ ...

  3. python学习笔记(十八)网络编程之requests模块

    上篇博客中我们使用python自带的urllib模块去请求一个网站,或者接口,但是urllib模块太麻烦了,传参数的话,都得是bytes类型,返回数据也是bytes类型,还得解码,想直接把返回结果拿出 ...

  4. struts2学习笔记之十四:使用注解配置Action(不是和spring集成使用)

    Struts2支持使用注解配置Action,减少配置文件的配置 Struts2如果要支持注解配置Action,需要插件的支持,导入插件struts2-convention-plugin-2.1.8.1 ...

  5. 红帽学习笔记[RHCSA] 第七课[网络配置相关]

    第七课[网络配置相关] 在Vmware中添加网卡 编辑 -> 编辑虚拟网络 -> 添加网络->随便选择一个如VMnet2-> 选择仅主机模式 -> 勾掉使用本地DHCP服 ...

  6. Linux系统学习笔记:文件I/O

    Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...

  7. Binder学习笔记(十二)—— binder_transaction(...)都干了什么?

    binder_open(...)都干了什么? 在回答binder_transaction(...)之前,还有一些基础设施要去探究,比如binder_open(...),binder_mmap(...) ...

  8. 深挖计算机基础:趣谈Linux操作系统学习笔记

    参考极客时间专栏<趣谈Linux操作系统>学习笔记 核心原理篇:内存管理 趣谈Linux操作系统学习笔记:第二十讲 趣谈Linux操作系统学习笔记:第二十一讲 趣谈Linux操作系统学习笔 ...

  9. linux 驱动学习笔记01--Linux 内核的编译

    由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...

随机推荐

  1. c++11——可变参数模板

    在c++11之前,类模板和函数模板只能含有固定数量的模板参数,c++11增加了可变模板参数特性:允许模板定义中包含0到任意个模板参数.声明可变参数模板时,需要在typename或class后面加上省略 ...

  2. MQTT的学习研究(八)基于HTTP DELETE MQTT 订阅消息服务端使用

    HTTP DELETE 订阅主题请求协议和响应协议http://publib.boulder.ibm.com/infocenter/wmqv7/v7r0/topic/com.ibm.mq.csqzau ...

  3. Docker源码分析(八):Docker Container网络(下)

    1.Docker Client配置容器网络模式 Docker目前支持4种网络模式,分别是bridge.host.container.none,Docker开发者可以根据自己的需求来确定最适合自己应用场 ...

  4. RDO部署多节点OpenStack Havana(OVS+GRE)

    RDO是由红帽RedHat公司推出的部署OpenStack集群的一个基于Puppet的部署工具,可以很快地通过RDO部署一套复杂的OpenStack环境,当前的RDO默认情况下,使用Neutron进行 ...

  5. 使用Eclipse(以及intellij IDEA)配合JDWP对服务器上部署的代码进行调试

    今天遇到了一个问题:同样的代码,在服务器上跑的时候会报空指针异常,但是在本地是没有问题的,看服务器上打印的日志只能看到异常信息,不能准确地定位到出问题的代码,于是就搜索了一下远程调试.结果还真的可以在 ...

  6. 分布式数据库主键id生成策略

    分布式数据库部署主要分为两种,一种是读写分离.这个需要弄主从数据库.主要是写的时候写主数据库,读的时候读从数据库.分散读取压力,对于读多写少的系统有利于 提高其性能.还有一种是分布式存储,这种主要是将 ...

  7. CH1602 The XOR Largest Pair【Trie树】

    1602 The XOR Largest Pair 0x10「基本数据结构」例题 描述 在给定的N个整数A1,A2……AN中选出两个进行xor运算,得到的结果最大是多少? 输入格式 第一行一个整数N, ...

  8. 徐州网络赛A-Hard To Prepare【dp】【位运算】【快速幂】

    After Incident, a feast is usually held in Hakurei Shrine. This time Reimu asked Kokoro to deliver a ...

  9. iptables,lokkit,ebtables,arptables---logrotate

    iptables,lokkit,ebtables,arptables logrotate  这五个位置也被称为五个钩子函数(hook functions),也叫五个规则链. 1.PREROUTING ...

  10. 运行mlflow命令报错 The 'nose' distribution was not found and is required by nose-exclude

    安装好mlflow之后命令行运行: mlflow 得到报错: 解决: sudo pip3 install nose