imx515 fec 驱动mii 的实现

1.        mii 的实现

初始化函数:fec_enet_init里初始化一个mii命令队列,mii_free指向空闲队列的头,mii_headmii_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);

}

 

你可能感兴趣的:(imx515 fec 驱动mii 的实现)