背景

参考

YT8531 YT8521驱动调试(一)_大牛攻城狮的博客-CSDN博客

原理图

也参考上述提到博客

不同点

接一,针对 YT8521

其实两个phy的外围接口电路涉及基本上移植,不通的就是phy地址的设计

但是YT8521实际使用过程中,需要配置两个寄存器

如下所示

mdio eth0 0x1e 0xa001

mdio eth0 0x1f 0x8160

翻了一下手册,这个寄存器地址是

 

调试的问题最终还是发现原理图的设计有问题,只是通过上述MDIO指令可以规避

一个是mode_sel的选择是否正确

一个是cfg_ldo电压选择是否正确

这上述配置,在原理图设计的时候都可以通过IO,YT8521的管脚进行选择

例如如下设计

 这里还设计一个问题就是在系统中使用mdio指令

mdio指令一般在uboot中使用的多,如下使用方法

mdio - MDIO utility commands

Usage:

mdio list - List MDIO buses

mdio read [.] - read PHY's register at .

mdio write [.] - write PHY's register at .

mdio rx [.] - read PHY's extended register at .

mdio wx [.] - write PHY's extended register at .

may be:

, and may be ranges, e.g. 1-5.4-0x1f.

=>

=> mdio list

这里提供一种linux系统mdio的配置方法

使用下面代码描述了在用户层访问smi/mdio总线, 读写phy芯片寄存器的通用代码。Linux内核2.6以上通用。需要根据自己的交叉编译环境,进行交叉编译,进行搭建交叉编译环境

如下所示,提供一个可以使用makefile的编写,需要替换自己的交叉编译环境

arm_cross_gcc = /home/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc

objects = mdio.o

mdio: $(objects)

$(arm_cross_gcc) -o mdio $(objects)

%.o : %.c

$(arm_cross_gcc) -c $<

.PHONY:clean

clean:

rm mdio $(objects)

@echo clean finish

将下面代码编译后,将可执行文件mdio

如下图所示

 

使用方法举例:

mdio eth0 1 读取phy寄存器1的数值

mdio eth0 0 0x1120 将0x1120写入 phy寄存器1

eth0 为mac层控制器的名称, 一般为eth0 或mgmt0

mdio.c代码如下,看起来还是比较容易理解的,主要是使用linux系统mii IO_CTL

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define reteck(ret) \

if(ret < 0){ \

printf("%m! \"%s\" : line: %d\n", __func__, __LINE__); \

goto lab; \

}

#define help() \

printf("mdio:\n"); \

printf("read operation: mdio reg_addr\n"); \

printf("write operation: mdio reg_addr value\n"); \

printf("For example:\n"); \

printf("mdio eth0 1\n"); \

printf("mdio eth0 0 0x12\n\n"); \

exit(0);

int sockfd;

int main(int argc, char *argv[])

{

if(argc == 1 || !strcmp(argv[1], "-h")){

help();

}

struct mii_ioctl_data *mii = NULL;

struct ifreq ifr;

int ret;

memset(&ifr, 0, sizeof(ifr));

strncpy(ifr.ifr_name, argv[1], IFNAMSIZ - 1);

sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);

reteck(sockfd);

//get phy address in smi bus

ret = ioctl(sockfd, SIOCGMIIPHY, &ifr);

reteck(ret);

mii = (struct mii_ioctl_data*)&ifr.ifr_data;

if(argc == 3){

mii->reg_num = (uint16_t)strtoul(argv[2], NULL, 0);

ret = ioctl(sockfd, SIOCGMIIREG, &ifr);

reteck(ret);

printf("read phy addr: 0x%x reg: 0x%x value : 0x%x\n\n", mii->phy_id, mii->reg_num, mii->val_out);

}else if(argc == 4){

mii->reg_num = (uint16_t)strtoul(argv[2], NULL, 0);

mii->val_in = (uint16_t)strtoul(argv[3], NULL, 0);

ret = ioctl(sockfd, SIOCSMIIREG, &ifr);

reteck(ret);

printf("write phy addr: 0x%x reg: 0x%x value : 0x%x\n\n", mii->phy_id, mii->reg_num, mii->val_in);

}

lab:

close(sockfd);

return 0;

}

 这样处理后,将mdio放到开发板文件系统的/sbin或者/bin下就可以使用mdio指令,进行愉快的调试了。

当然也可以在启动设置项,配置本文开头提到的0xa001寄存器地址了。

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: