1. xavier与marvell 88e1512 的原理图连接
为RGMII接口,连接定义参考如:
其中,发送端有:
n TXC:发送端参考时钟
n TD[0:3]:发送数据引脚
n TX_CTL:发送控制引脚
TX_CTL信号线上传送TX_EN和TX_ER两种信息,在TXC的上升沿发送TX_EN,下降沿发送TX_ER。
注:在千兆速率下,向PHY提供TXC信号,TXD、TXEN、TXER信号与此时钟信号同步。
在10/100M速率下,PHY提供 TXCLK时钟信号,其它信号与此信号同步。其工作频率为25MHz(100M网络)或2.5MHz(10M网络)。
类似于如下的MII接口模式:
88E1512RGMII寄存器说明
从代码看速率自适应的过程
硬件 xavier
软件 linux-4.9
kernel-4.9/kernel/nvidia/drivers/net/ethernet/nvidia/eqos/init.c
eqos_init_module-> platform_driver_register(&eqos_driver)
static struct platform_driver eqos_driver = {
.probe = eqos_probe,
.remove = eqos_remove,
eqos_open
eqos_init_phy
of_phy_connect(dev, pdata->phy_node,
&eqos_adjust_link, 0, pdata->interface);
关键是这个判断速率的函数:eqos_adjust_link
MAC配置100M,1000M hw_if->set_gmii_speed
static INT set_gmii_speed(struct eqos_prv_data *pdata)
{
MAC_MCR_PS_WR(0);
MAC_MCR_FES_WR(0);
if (tegra_platform_is_unit_fpga())
CLK_CRTL0_TX_CLK_WR(0);
return Y_SUCCESS;
}
```c
MAC配置100M:hw_if->set_mii_speed_100
```c
static INT set_mii_speed_100(struct eqos_prv_data *pdata)
{
MAC_MCR_PS_WR(0x1);
MAC_MCR_FES_WR(0x1);
if (tegra_platform_is_unit_fpga())
CLK_CRTL0_TX_CLK_WR(0);
return Y_SUCCESS;
}
```c
MAC配置10M :
```c
static INT set_mii_speed_10(struct eqos_prv_data *pdata)
{
MAC_MCR_PS_WR(0x1);
MAC_MCR_FES_WR(0);
if (tegra_platform_is_unit_fpga())
CLK_CRTL0_TX_CLK_WR(1);
return Y_SUCCESS;
}
#define MAC_MCR_PS_WR(data) do {\
ULONG v;\
MAC_MCR_RD(v);\
v = (v & (MAC_MCR_RES_WR_MASK_7))\
|(((0) & (MAC_MCR_MASK_7))<<7);\
v = ((v & MAC_MCR_PS_WR_MASK)\
|((data & MAC_MCR_PS_MASK)<<15));\
MAC_MCR_WR(v);\
} while (0)
配置时钟速率
if (speed_changed) {
hw_if->set_tx_clk_speed(pdata, phydev->speed);
/* recalibrate if speed 10 to 100 or 1000mbps */
if (pdata->oldspeed == SPEED_10)
hw_if->pad_calibrate(pdata);
pdata->oldspeed = pdata->speed;
}
static INT set_tx_clk_speed(struct eqos_prv_data *pdata, INT speed)
{
/* set eqos_tx clock to 125/25/2.5MHz based on speed */
if (tegra_platform_is_silicon()) {
struct platform_device *pdev = pdata->pdev;
int ret;
ret = clk_set_rate(pdata->tx_clk,
(speed == SPEED_10) ? 2500 * 1000 :
(speed ==
SPEED_100) ? 25000 * 1000 : 125000 * 1000);
if (ret) {
dev_err(&pdev->dev, "failed to set tx_clk to %sMHz\n",
(speed == SPEED_10) ? "2.5" :
(speed == SPEED_100) ? "25" : "125");
return Y_FAILURE;
}
}
return Y_SUCCESS;
}