1. mii 的实现
初始化函数:fec_enet_init里初始化一个mii命令队列,mii_free指向空闲队列的头,mii_head和mii_tail在队列中加入第一项时初始化,指示待处理命令队列。mii_queue往队列中放入一个待处理命令,若列表为空,则直接改变mii寄存器的值。
fec_enet_mii处理mii中断,即在mii操作完成后执行回调函数func。
mk_mii_read(REG) 用于组装读PHY寄存器的命令;
mk_mii_write(REG)用于组装写PHY寄存器的命令;
1) 原型声明
typedef struct mii_list {
uint mii_regval;
void (*mii_func)(uint val, struct net_device *dev);
struct mii_list *mii_next;
} mii_list_t;
#define NMII 20
static mii_list_t mii_cmds[NMII];
static mii_list_t *mii_free;
static mii_list_t *mii_head;
static mii_list_t *mii_tail;
static int mii_queue(struct net_device *dev, int request,
void (*func)(uint, struct net_device *));
/* Make MII read/write commands for the FEC.
*/
#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | /
(VAL & 0xffff))
#define mk_mii_end 0
2) 相关函数
创建mii命令队列:
nt __init fec_enet_init(struct net_device *dev)
{
…
/*初始化一个空的mii命令列表*/
for (i=0; i<NMII-1; i++)
mii_cmds[i].mii_next = &mii_cmds[i+1];
/*mii_free指向可用节点*/
mii_free = mii_cmds;
...
}
mii中断:
fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
{
…
/*响应中断调用fec_enet_mii*/
if (int_events & FEC_ENET_MII)
fec_enet_mii(dev);
…
}
mii中断处理程序: /* called from interrupt context */
static void fec_enet_mii(struct net_device *dev) { struct fec_enet_private *fep; volatile fec_t *ep; mii_list_t *mip; uint mii_reg; fep = netdev_priv(dev); spin_lock_irq(&fep->mii_lock);
ep = fep->hwp; /* 指向fec映射地址 */ mii_reg = ep->fec_mii_data; if ((mip = mii_head) == NULL) { printk("MII and no head!/n"); goto unlock; } if (mip->mii_func != NULL) (*(mip->mii_func))(mii_reg, dev); /* 通过mii获得的数据供用户使用 */ mii_head = mip->mii_next; mip->mii_next = mii_free; mii_free = mip; if ((mip = mii_head) != NULL) ep->fec_mii_data = mip->mii_regval;
unlock: spin_unlock_irq(&fep->mii_lock); }
配置fec接口模式为mii
static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
{
u32 rate;
struct clk *clk;
volatile fec_t *fecp;
fecp = fep->hwp;
fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
fecp->fec_x_cntrl = 0x00;
/*
* Set MII speed to 2.5 MHz
*/
clk = clk_get(NULL, "fec_clk");
rate = clk_get_rate(clk);
clk_put(clk);
fep->phy_speed =
((((rate / 2 + 4999999) / 2500000) / 2) & 0x3F) << 1;
fecp->fec_mii_speed = fep->phy_speed;
fec_restart(dev, 0);
}
本文介绍了FEC网络控制器中的MII模块实现细节,包括初始化过程、MII命令队列管理、读写PHY寄存器的命令组装及MII中断处理流程。详细解释了fec_enet_init函数如何初始化MII命令队列,fec_enet_mii函数如何处理MII中断,以及mk_mii_read和mk_mii_write宏如何组装读写命令。
2243

被折叠的 条评论
为什么被折叠?



