一:uboot的启动过程的基本知识
uboot的基本移植过程:分为步奏1 ,步奏2;
代码入口:u-boot/arch/arm/cpu/u-boot.lds连接文件。ENTRY(_start):代码的入口函数。
\board\ti\am335x\u-boot.lds保存了U-boot数据代码段在内存中的存放情况
启动步奏:_start标号:arch\arm\cpu\armv7\start.s复位;
bl cpu_init_cp15:主要对cp15协处理器进行初始化,关闭MMU和tlb(处理器访问内存时做地址转换),和cache。
然后调用:cpu_init_crit。:跳转到开发板的相关的初始化代码,初始化相关寄存器
arch\arm\cpu\armv7\lowlevel_init.S:特定开发板的设置代码。
核心代码:lowlevel_init。跳转到:s_init(void)(板卡级别c的程序)\arch\arm\cpu\armv7\am33xx\board.c-s_init
_main() ENTRY(_main)
1:arch/arm/lib/crt0.s中跳转到ldr pc, =board_init_r。(\arch\arm\lib\board.c中)
进入到板卡的运行程序中。
函数调用流程:(am3352 的网口cpsw网卡驱动只能驱动两个网口)
eth_initialize(gd->bd)->phy_init()->(phy驱动初始化,用来配置phy)
phy_smsc_init();用来注册phy的驱动初始化的接口
对phy的初始化操作:static struct phy_driver lan8710_driver = { //驱动程序 (用来定义phy 的行为)
.name = "SMSC LAN8710/LAN8720",
.uid = 0x0007c0f0,
.mask = 0xffff0,
.features = PHY_BASIC_FEATURES,
.config = &genphy_config_aneg, //驱动配置
.startup = &genphy_startup, //驱动开始
.shutdown = &genphy_shutdown,
};
//用来初始化335x的网卡驱动芯片。
board_eth_init:读mac地址
writel(MII_MODE_ENABLE, &cdev->miisel):mii操作寄存器
->board_eth_init(\board\ti\am335x\board.c)->cpsw_register(&cpsw_data)->cpsw_phy_init->phy_connect
根据寄存器得到存放的mac地址,
->phy_find_by_mask(确保phy已经启动复位)
网卡配置的slave的配置(也就是网卡对phy的配置参数)
网卡对于phy寄存器的基址。
static struct cpsw_slave_data cpsw_slaves[] = {
{
.slave_reg_ofs = 0x208, //从设备寄存器的偏移地址
.sliver_reg_ofs = 0xd80,
.phy_addr = 0,
},
{
.slave_reg_ofs = 0x308,
.sliver_reg_ofs = 0xdc0,
.phy_addr = 1,
},
};
rv = cpsw_register(&cpsw_data);:注册cpsw网卡驱动
网卡对主的cpsw的配置的默认参数:static struct cpsw_platform_data cpsw_data = {
.mdio_base = CPSW_MDIO_BASE, 0x4A100800 mdio基地址
.cpsw_base = CPSW_BASE, cpsw基地址
.mdio_div = 0xff,
.channels = 8, dma通道号
.cpdma_reg_ofs = 0x800, dma寄存器偏移值
.slaves = 1,
.slave_data = cpsw_slaves,
.ale_reg_ofs = 0xd00, 地址搜寻寄存器偏移值
.ale_entries = 1024, 地址表大小
.host_port_reg_ofs = 0x108, port寄存器偏移值
.hw_stats_reg_ofs = 0x900, 硬件状态寄存器偏移值
.bd_ram_ofs = 0x2000, buffer 描述ram偏移值
.mac_control = (1 << 5),
.control = cpsw_control,
.host_port_num = 0,
.version = CPSW_CTRL_VERSION_2,};
for_each_slave(slave, priv) {
cpsw_slave_setup(slave, idx, priv);
printf("slave->slave_num=%d,\n",slave->slave_num);
idx = idx + 1;
}判断搜寻phy驱动
dev->init = cpsw_init;网卡驱动初始化,网卡驱动发送,网卡驱动接收
dev->halt = cpsw_halt;停止
dev->send = cpsw_send;
dev->recv = cpsw_recv;
eth_register(dev);注册网卡
cpsw_mdio_init:注册mdio总线驱动。根据mdio寄存器控住总线。mdio总线初始化,初始化phy设备的读写操作接口函数注册mii_dev总线设备:主要参数名称,读操作,写操作。
priv->bus = miiphy_get_dev_by_name(dev->name);根据总线名称得到总线。
cpsw_phy_init:phy设备初始化接口
phy_find_by_mask->create_phy_by_mask->phy_device_create(创建phy设备)->get_phy_driver查询得到phy的设备。->phy_probe使能phy设备。
for_active_slave(slave, priv)搜寻实际的从设备,确定设备参数。
phydev = phy_connect(priv->bus, slave->data->phy_addr,dev,slave->data->phy_if);->phy_reset将网卡设备与phy设备连接
phy_config->board_phy_config-> .config = &genphy_config_aneg,
以上就是phy驱动基于cpsw的基本流程。
小知识点:ffs用来查找整数中第一个bit为1的数。