JL2101 是一颗和Realtek Rtl8211F pin to pin 的国产1000M PHY IC
由于他和RTL8211F 管脚和供电电压一致,所以我们一开始按照RK的建议直接用RK RTL8211F 的配置进行编译:
RK3566 和RK3568 等IC 需要注意domain 工作电压配置,按照实际硬件配置,软件上做相应的电压配置,如果配置错误可能有该组电压域VDDIO 失效的可能性:
PMUIO2 Supply Power Voltage1:3300000
VCCIO1 Supply Power Voltage1:3300000
VCCIO3 Supply Power Voltage1:3300000
VCCIO4 Supply Power Voltage1:1800000
VCCIO5 Supply Power Voltage1:3300000
VCCIO6 Supply Power Voltage1:1800000
VCCIO7 Supply Power Voltage1:3300000
kernel$ vi drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
1.走Linux通用驱动,初始化阶段硬复位或软复位都会有DMA报错,使PHY 进入Power down。
使用RC上电复位跳过初始化阶段的设置,可正常启动。
解决方案为:在初始化DMA前加2s延时,等待PHY的RX clock ready后再初始化DMA
修改代码
kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
static int stmmac_open(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
u32 chan;
int ret;
if (priv->hw->pcs != STMMAC_PCS_RGMII &&
priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI) {
ret = stmmac_init_phy(dev);
if (ret) {
netdev_err(priv->dev,
"%s: Cannot attach to PHY (error: %d)\n",
__func__, ret);
return ret;
}
}
/* Extra statistics */
memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
priv->xstats.threshold = tc;
priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
priv->rx_copybreak = STMMAC_RX_COPYBREAK;
ret = alloc_dma_desc_resources(priv);
if (ret < 0) {
netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n",
__func__);
goto dma_desc_error;
}
ret = init_dma_desc_rings(dev, GFP_KERNEL);
if (ret < 0) {
netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n",
__func__);
goto init_error;
}
+#if 1
+//#ifdef CONFIG_JLSEMI_PHY
+ printk("sam -------bootup add 2s delay time.\n");
+//sam jiang loged
+ mdelay(2500);
+#endif
ret = stmmac_hw_setup(dev, true);
if (ret < 0) {
netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
goto init_error;
}
stmmac_init_tx_coalesce(priv);
int stmmac_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
if (!netif_running(ndev))
return 0;
/* Power Down bit, into the PM register, is cleared
* automatically as soon as a magic packet or a Wake-up frame
* is received. Anyway, it's better to manually clear
* this bit because it can generate problems while resuming
* from another devices (e.g. serial console).
*/
if (device_may_wakeup(priv->device)) {
mutex_lock(&priv->lock);
stmmac_pmt(priv, priv->hw, 0);
mutex_unlock(&priv->lock);
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
/* enable the clk previously disabled */
clk_prepare_enable(priv->plat->stmmac_clk);
clk_prepare_enable(priv->plat->pclk);
if (priv->plat->clk_ptp_ref && IS_ENABLED(CONFIG_STMMAC_PTP))
clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
}
mutex_lock(&priv->lock);
stmmac_reset_queues_param(priv);
stmmac_free_tx_skbufs(priv);
stmmac_clear_descriptors(priv);
+ #if 1
+// #ifdef CONFIG_JLSEMI_PHY
+ printk("sam -------resume add 2s delay time.\n");
+ //sam jiang loged
+ mdelay(2000);
+ #endif
stmmac_hw_setup(ndev, false);
stmmac_init_tx_coalesce(priv);
stmmac_set_rx_mode(ndev);
stmmac_enable_all_queues(priv);
netif_device_attach(ndev);
-------------------------------------------------------------------------------------
GMAC1配置为 RGMII Crystal 25M for PHY, PLL output 125M for TX_CLK
&gmac1 {
phy-mode = "rgmii";
clock_in_out = "output";
snps,reset-gpio = <&gpio2 RK_PD1 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
/* Reset time is 20ms, 100ms for rtl8211f */
snps,reset-delays-us = <0 20000 100000>;
assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>;
assigned-clock-rates = <0>, <125000000>;
pinctrl-names = "default";
pinctrl-0 = <&gmac1m0_miim
&gmac1m0_tx_bus2
&gmac1m0_rx_bus2
&gmac1m0_rgmii_clk
&gmac1m0_rgmii_bus>;
tx_delay = <0x4f>;
rx_delay = <0x26>;
phy-handle = <&rgmii_phy1>;
status = "okay";
};
&mdio1 {
rgmii_phy1: phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0x0>;
};
};
修改
kernel/arch/arm64/boot/dts/rockchip/rk3566-box-demo-v10.dtsi
+/*
-&gmac1 {
- phy-mode = "rgmii";
- clock_in_out = "input";
-
- snps,reset-gpio = <&gpio4 RK_PC2 GPIO_ACTIVE_LOW>;
- snps,reset-active-low;
- //Reset time is 20ms, 100ms for rtl8211f
- snps,reset-delays-us = <0 20000 100000>;
- assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
- assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&gmac1_clkin>;
-
- assigned-clock-rates = <0>, <125000000>;
- pinctrl-names = "default";
- pinctrl-0 = <&gmac1m1_miim
- &gmac1m1_tx_bus2
- &gmac1m1_rx_bus2
- &gmac1m1_rgmii_clk
- &gmac1m1_rgmii_bus
- &gmac1m1_clkinout>;
-
- tx_delay = <0x4b>;
- rx_delay = <0x2b>;
-
- phy-handle = <&rgmii_phy1>;
- status = "okay";
-};
+*/
+&gmac1 {
+ phy-mode = "rgmii";
+ clock_in_out = "output";
+ snps,reset-gpio = <&gpio4 RK_PC2 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ /* Reset time is 20ms, 100ms for rtl8211f */
+ snps,reset-delays-us = <0 100000 200000>;
+ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
+ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>;
+ assigned-clock-rates = <0>, <125000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1m1_miim
+ &gmac1m1_tx_bus2
+ &gmac1m1_rx_bus2
+ &gmac1m1_rgmii_clk
+ &gmac1m1_rgmii_bus>;
+ tx_delay = <0x4b>;
+ rx_delay = <0x26>;
+ phy-handle = <&rgmii_phy1>;
+ status = "okay";
+};
修改后发现有时候初始化的时候 phy reset 失败,我们将Phy reset 的时间加长
snps,reset-delays-us = <0 100000 200000>;
如上图所填参数