zynq u-boot网络配置
来源:互联网 发布:平价凉鞋推荐知乎 编辑:程序博客网 时间:2024/05/24 06:38
原文地址:http://blog.csdn.net/zhaoxinfan/article/details/69662074#comments
在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 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启动就可以了。
阅读全文
0 0
- zynq u-boot网络配置
- zynq u-boot配置
- Zynq-Linux移植学习笔记之十-u-boot网络配置
- Zynq-Linux移植学习笔记之十-u-boot网络配置
- Zynq-Linux移植学习笔记之十-u-boot网络配置
- zynq 之u-boot
- Zynq boot mode MIO 配置
- ZYNQ 系统搭建 生成 U-BOOT
- ZYNQ平台学习--(3)u-boot编译
- U-Boot网络问题
- U-Boot网络控制台
- zynq u-boot驱动串口打印乱码或者无打印
- [U-Boot] [PATCH v5 29/30] zynq: Enable CONFIG_DEFAULT_DEVICE_TREE
- zynq学习笔记二:编译U-Boot(zybo)
- u-boot命令配置
- 配置u-boot
- u-boot 2、配置
- U-Boot配置过程
- read/fread write/fwrite 的实现原理
- 美俄总统今将在G20首会,为何握手比会谈结果更吸睛
- 使用TabHost点击第一次无法获得数据的问题,自定义TabHost。
- CSRF原理
- 长时间后mysql自动关闭连接
- zynq u-boot网络配置
- 多线程编程
- 几种常用的排序算法
- 【集训】jzoj 2017.7.7 noip模拟赛A 总结
- 欢迎使用CSDN-markdown编辑器
- 关于打印机打印网页出现字迹显示不全的问题心得
- Git常用命令大全,迅速提升你的Git水平
- 高位优先字符串排序
- MySQL的重新安装或卸载、以及删除注册表的信息