浏览代码

[bsp/cvitek] eth driver support phy link detect

Signed-off-by: flyingcys <flyingcys@163.com>
flyingcys 11 月之前
父节点
当前提交
2e224b30ad

+ 55 - 9
bsp/cvitek/drivers/drv_eth.c

@@ -27,6 +27,8 @@
 // #define ETH_RX_DUMP
 
 #define MAX_ADDR_LEN        6
+#define DETECT_THREAD_PRIORITY         RT_THREAD_PRIORITY_MAX - 2
+#define DETECT_THREAD_STACK_SIZE       4096
 
 struct _dw_eth
 {
@@ -109,7 +111,7 @@ static int cvi_eth_mac_phy_enable(uint32_t enable)
     }
 
     /* set mac address */
-    memcpy(addr.b, g_mac_addr, sizeof(g_mac_addr));
+    rt_memcpy(addr.b, g_mac_addr, sizeof(g_mac_addr));
     ret = cvi_eth_mac_set_macaddr(g_mac_handle, &addr);
     if (ret != 0)
     {
@@ -174,6 +176,36 @@ static void dw_gmac_handler_irq(int vector, void *param)
     }
 }
 
+static void phy_link_detect(void *param)
+{
+    int link_status = -1;
+    int link_status_old = -1;
+    int ret = -1;
+
+    while (1)
+    {
+        link_status = eth_phy_update_link(g_phy_handle);
+        LOG_D("eth link status: %d", link_status);
+
+        if (link_status_old != link_status)
+        {
+            if (link_status == 0)
+            {
+                LOG_I("eth link up");
+                eth_device_linkchange(&(dw_eth_device.parent), RT_TRUE);
+            }
+            else
+            {
+                LOG_I("eth link down");
+                eth_device_linkchange(&(dw_eth_device.parent), RT_FALSE);
+            }
+
+            link_status_old = link_status;
+        }
+        rt_thread_delay(RT_TICK_PER_SECOND);
+    }
+}
+
 static rt_err_t rt_dw_eth_init(rt_device_t dev)
 {
     struct _dw_eth *dw_eth;
@@ -209,8 +241,23 @@ static rt_err_t rt_dw_eth_init(rt_device_t dev)
     rt_hw_interrupt_install(dw_eth->irq, dw_gmac_handler_irq, g_mac_handle, "e0");
     rt_hw_interrupt_umask(dw_eth->irq);
 
-    /* change device link status */
-    eth_device_linkchange(&(dw_eth_device.parent), RT_TRUE);
+    LOG_D("PHY MAC init success");
+
+    rt_thread_t link_detect;
+    link_detect = rt_thread_create("link_detect",
+                            phy_link_detect,
+                            (void *)&dw_eth_device,
+                            DETECT_THREAD_STACK_SIZE,
+                            DETECT_THREAD_PRIORITY,
+                            2);
+    if (link_detect != RT_NULL)
+    {
+        rt_thread_startup(link_detect);
+    }
+    else
+    {
+        err = -RT_ERROR;
+    }
 
     return RT_EOK;
 }
@@ -275,7 +322,7 @@ struct pbuf* rt_dw_eth_rx(rt_device_t dev)
     uint32_t i = 0;
 
     int32_t len = cvi_eth_mac_read_frame(g_mac_handle, RecvDataBuf, GMAC_BUF_LEN);
-    if((len <= 0) || (len > GMAC_BUF_LEN))
+    if ((len <= 0) || (len > GMAC_BUF_LEN))
     {
         return NULL;
     }
@@ -308,11 +355,11 @@ struct pbuf* rt_dw_eth_rx(rt_device_t dev)
         * actually received size. In this case, ensure the tot_len member of the
         * pbuf is the sum of the chained pbuf len members.
         */
-        memcpy((u8_t*)q->payload, (u8_t*)&RecvDataBuf[i], q->len);
+        rt_memcpy((u8_t*)q->payload, (u8_t*)&RecvDataBuf[i], q->len);
         i = i + q->len;
     }
 
-    if((i != p->tot_len) || (i > len))
+    if ((i != p->tot_len) || (i > len))
     {
         return NULL;
     }
@@ -348,14 +395,14 @@ rt_err_t rt_dw_eth_tx(rt_device_t dev, struct pbuf* p)
         variable. */
         MEMCPY((uint8_t *)&SendDataBuf[len], (uint8_t *)q->payload, q->len);
         len = len + q->len;
-        if((len > GMAC_BUF_LEN) || (len > p->tot_len))
+        if ((len > GMAC_BUF_LEN) || (len > p->tot_len))
         {
             LOG_E("rt_dw_eth_tx: error, len=%d, tot_len=%d", len, p->tot_len);
             return -RT_ERROR;
         }
     }
 
-    if(len == p->tot_len)
+    if (len == p->tot_len)
     {
         if (cvi_eth_mac_send_frame(g_mac_handle, SendDataBuf, len) < 0)
             ret = -RT_ERROR;
@@ -405,7 +452,6 @@ static int rthw_eth_init(void)
         LOG_E("eth_device_init failed: %d", ret);
         return ret;
     }
-
     return RT_EOK;
 }
 INIT_DEVICE_EXPORT(rthw_eth_init);

+ 63 - 30
bsp/cvitek/drivers/libraries/eth/cvi_eth_phy.c

@@ -1,6 +1,18 @@
 /*
-* Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
-*/
+ * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 #include <rtthread.h>
 
 #include "cvi_eth_phy.h"
@@ -88,6 +100,51 @@ static int32_t eth_read_phy_id(eth_phy_priv_t *priv, uint8_t phy_addr, uint32_t
     return 0;
 }
 
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline int32_t ffs(int32_t x)
+{
+    int32_t r = 1;
+
+    if (!x)
+        return 0;
+
+    if (!(x & 0xffff))
+    {
+        x >>= 16;
+        r += 16;
+    }
+
+    if (!(x & 0xff))
+    {
+        x >>= 8;
+        r += 8;
+    }
+
+    if (!(x & 0xf))
+    {
+        x >>= 4;
+        r += 4;
+    }
+
+    if (!(x & 3))
+    {
+        x >>= 2;
+        r += 2;
+    }
+
+    if (!(x & 1))
+    {
+        x >>= 1;
+        r += 1;
+    }
+
+    return r;
+}
+
 static eth_phy_dev_t * eth_get_phy_by_mask(eth_phy_priv_t *priv, uint32_t phy_mask, phy_if_mode_t interface)
 {
     uint32_t phy_id = 0xffffffff;
@@ -283,33 +340,9 @@ int32_t genphy_update_link(eth_phy_dev_t *phy_dev)
 
     if ((phy_dev->priv->link_info.autoneg == CSI_ETH_AUTONEG_ENABLE) &&
         !(mii_reg & CVI_BMSR_ANEGCOMPLETE)) {
-        int i = 0;
-
-        rt_kprintf("%s waiting for PHY auto negotiation to complete...\n",
-            phy_dev->name);
-        while (!(mii_reg & CVI_BMSR_ANEGCOMPLETE)) {
-            /*
-             * Timeout reached ?
-             */
-            if (i > CVI_PHY_ANEG_TIMEOUT) {
-                rt_kprintf("TIMEOUT!\n");
-                phy_dev->link_state = ETH_LINK_DOWN;
-                return -1;
-            }
-
-            // if ((i++ % 1000) == 0)
-            //  rt_kprintf(".");
-            i ++;
-
-            rt_hw_us_delay(1000);   /* 1 ms */
-
-            ret = eth_phy_read(phy_dev->priv, phy_addr, CVI_MII_BMSR, &mii_reg);
-            if (ret != 0) {
-                return ret;
-            }
-        }
-        rt_kprintf("auto negotiation Done!\n");
-        phy_dev->link_state = ETH_LINK_UP;
+
+        phy_dev->link_state = ETH_LINK_DOWN;
+        return -1;
     } else {
 
         /* Read the link a second time to clear the latched state */
@@ -590,7 +623,7 @@ eth_phy_handle_t cvi_eth_phy_init(csi_eth_phy_read_t  fn_read, csi_eth_phy_write
     phy_dev = eth_connect_phy(priv, phy_mask, interface);
     if (phy_dev == NULL) {
         rt_kprintf("No phy device found!\n");
-        return;
+        return NULL;
     }
     rt_kprintf("connect phy id: 0x%X\n", phy_dev->phy_id);
 

+ 16 - 34
bsp/cvitek/drivers/libraries/eth/cvi_eth_phy.h

@@ -1,5 +1,17 @@
 /*
- * Copyright (C) 2019-2020 AlibabaGroup Holding Limited
+ * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 /******************************************************************************
  * @file     phy.h
@@ -359,40 +371,10 @@ int32_t eth_phy_update_link(eth_phy_handle_t handle);
 int32_t genphy_config(eth_phy_dev_t *phy_dev);
 int32_t genphy_update_link(eth_phy_dev_t *phy_dev);
 
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
+int32_t cvi_eth_phy_power_control(eth_phy_handle_t handle, eth_power_state_t state);
+
+eth_phy_handle_t cvi_eth_phy_init(csi_eth_phy_read_t  fn_read, csi_eth_phy_write_t fn_write);
 
-// static inline int32_t ffs(int32_t x)
-// {
-//  int32_t r = 1;
-
-//  if (!x)
-//      return 0;
-//  if (!(x & 0xffff)) {
-//      x >>= 16;
-//      r += 16;
-//  }
-//  if (!(x & 0xff)) {
-//      x >>= 8;
-//      r += 8;
-//  }
-//  if (!(x & 0xf)) {
-//      x >>= 4;
-//      r += 4;
-//  }
-//  if (!(x & 3)) {
-//      x >>= 2;
-//      r += 2;
-//  }
-//  if (!(x & 1)) {
-//      x >>= 1;
-//      r += 1;
-//  }
-//  return r;
-// }
 
 #ifdef __cplusplus
 }

+ 27 - 15
bsp/cvitek/drivers/libraries/eth/dw_eth_mac.c

@@ -1,10 +1,23 @@
 /*
-* Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
-*/
+ * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 #include <rtthread.h>
 
 #include "dw_eth_mac.h"
 #include "cache.h"
+#include "string.h"
 
 #define roundup(x, y) (                 \
 {                           \
@@ -91,7 +104,7 @@ static void tx_descs_init(eth_mac_handle_t handle)
     desc_p->dmamac_next = (unsigned long)&desc_table_p[0];
 
     /* Flush all Tx buffer descriptors at once */
-    rt_hw_cpu_dcache_clean((unsigned long)priv->tx_mac_descrtable, sizeof(priv->tx_mac_descrtable));
+    rt_hw_cpu_dcache_clean((void *)priv->tx_mac_descrtable, sizeof(priv->tx_mac_descrtable));
 
     dma_reg->txdesclistaddr = (unsigned long)&desc_table_p[0];
 
@@ -114,7 +127,7 @@ static void rx_descs_init(eth_mac_handle_t handle)
      * Otherwise there's a chance to get some of them flushed in RAM when
      * GMAC is already pushing data to RAM via DMA. This way incoming from
      * GMAC data will be corrupted. */
-    rt_hw_cpu_dcache_clean((unsigned long)rxbuffs, CVI_RX_TOTAL_BUFSIZE);
+    rt_hw_cpu_dcache_clean((void *)rxbuffs, CVI_RX_TOTAL_BUFSIZE);
 
     for (idx = 0; idx < CVI_CONFIG_RX_DESCR_NUM; idx++) {
         desc_p = &desc_table_p[idx];
@@ -132,7 +145,7 @@ static void rx_descs_init(eth_mac_handle_t handle)
     desc_p->dmamac_next = (unsigned long)&desc_table_p[0];
 
     /* Flush all Rx buffer descriptors at once */
-    rt_hw_cpu_dcache_clean((unsigned long)priv->rx_mac_descrtable, sizeof(priv->rx_mac_descrtable));
+    rt_hw_cpu_dcache_clean((void *)priv->rx_mac_descrtable, sizeof(priv->rx_mac_descrtable));
 
     dma_reg->rxdesclistaddr = (unsigned long)&desc_table_p[0];
 
@@ -238,8 +251,8 @@ static int32_t designware_eth_enable(eth_mac_handle_t handle, int32_t control)
     struct dw_gmac_mac_regs *mac_reg = mac_dev->priv->mac_regs_p;
     eth_link_state_t link_state = mac_dev->phy_dev->link_state;
 
-    if (link_state == ETH_LINK_DOWN)
-        return -1;
+    // if (link_state == ETH_LINK_DOWN)
+    //     return -1;
 
     switch (control) {
     case CSI_ETH_MAC_CONTROL_TX:
@@ -320,7 +333,7 @@ static int32_t designware_eth_send(eth_mac_handle_t handle, const uint8_t *frame
 
     /* Check if the descriptor is owned by CPU */
     while (1) {
-        rt_hw_cpu_dcache_invalidate(desc_start, desc_end - desc_start);
+        rt_hw_cpu_dcache_invalidate((void *)desc_start, desc_end - desc_start);
         if (!(desc_p->txrx_status & CVI_DESC_TXSTS_OWNBYDMA)) {
             break;
         }
@@ -335,7 +348,7 @@ static int32_t designware_eth_send(eth_mac_handle_t handle, const uint8_t *frame
     memcpy((void *)data_start, frame, length);
 
     /* Flush data to be sent */
-    rt_hw_cpu_dcache_clean(data_start, data_end - data_start);
+    rt_hw_cpu_dcache_clean((void *)data_start, data_end - data_start);
 
 #if defined(CONFIG_DW_ALTDESCRIPTOR)
     desc_p->txrx_status |= CVI_DESC_TXSTS_TXFIRST | CVI_DESC_TXSTS_TXLAST;
@@ -355,7 +368,7 @@ static int32_t designware_eth_send(eth_mac_handle_t handle, const uint8_t *frame
 #endif
 
     /* Flush modified buffer descriptor */
-    rt_hw_cpu_dcache_clean(desc_start, desc_end - desc_start);
+    rt_hw_cpu_dcache_clean((void *)desc_start, desc_end - desc_start);
 
     /* Test the wrap-around condition. */
     if (++desc_num >= CVI_CONFIG_TX_DESCR_NUM)
@@ -383,7 +396,7 @@ static int32_t designware_eth_recv(eth_mac_handle_t handle, uint8_t **packetp)
     uint64_t data_end;
 
     /* Invalidate entire buffer descriptor */
-    rt_hw_cpu_dcache_invalidate(desc_start, desc_end - desc_start);
+    rt_hw_cpu_dcache_invalidate((void *)desc_start, desc_end - desc_start);
     status = desc_p->txrx_status;
     /* Check  if the owner is the CPU */
     if (!(status & CVI_DESC_RXSTS_OWNBYDMA)) {
@@ -391,7 +404,7 @@ static int32_t designware_eth_recv(eth_mac_handle_t handle, uint8_t **packetp)
              CVI_DESC_RXSTS_FRMLENSHFT;
         /* Invalidate received data */
         data_end = data_start + roundup(length, DW_GMAC_DMA_ALIGN);
-        rt_hw_cpu_dcache_invalidate(data_start, data_end - data_start);
+        rt_hw_cpu_dcache_invalidate((void *)data_start, data_end - data_start);
         *packetp = (uint8_t *)((uint64_t)desc_p->dmamac_addr);
     }
 
@@ -415,7 +428,7 @@ static int32_t designware_free_pkt(eth_mac_handle_t handle)
     desc_p->txrx_status |= CVI_DESC_RXSTS_OWNBYDMA;
 
     /* Flush only status field - others weren't changed */
-    rt_hw_cpu_dcache_clean(desc_start, desc_end - desc_start);
+    rt_hw_cpu_dcache_clean((void *)desc_start, desc_end - desc_start);
 
     /* Test the wrap-around condition. */
     if (++desc_num >= CVI_CONFIG_RX_DESCR_NUM)
@@ -619,10 +632,9 @@ int32_t cvi_eth_mac_set_macaddr(eth_mac_handle_t handle, const eth_mac_addr_t *m
   \param[in]   handle  ethernet handle
   \param[in]   frame  Pointer to frame buffer with data to send
   \param[in]   len    Frame buffer length in bytes
-  \param[in]   flags  Frame transmit flags (see CSI_ETH_MAC_TX_FRAME_...)
   \return      error code
 */
-int32_t cvi_eth_mac_send_frame(eth_mac_handle_t handle, const uint8_t *frame, uint32_t len, uint32_t flags)
+int32_t cvi_eth_mac_send_frame(eth_mac_handle_t handle, const uint8_t *frame, uint32_t len)
 {
     RT_ASSERT(handle);
     RT_ASSERT(frame);

+ 92 - 3
bsp/cvitek/drivers/libraries/eth/dw_eth_mac.h

@@ -1,7 +1,18 @@
 /*
-* Copyright (C) Cvitek Co., Ltd. 2019-2022. All rights reserved.
-*/
-
+ * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 #ifndef _DW_GMAC_182x_H_
 #define _DW_GMAC_182x_H_
 
@@ -327,6 +338,84 @@ static inline void *memalign(uint32_t align, uint32_t size, void **mem_unalign)
     }
     return mem;
 }
+/**
+  \brief       Write Ethernet PHY Register through Management Interface.
+  \param[in]   handle  ethernet handle
+  \param[in]   phy_addr  5-bit device address
+  \param[in]   reg_addr  5-bit register address
+  \param[in]   data      16-bit data to write
+  \return      error code
+*/
+int32_t dw_eth_mac_phy_write(eth_mac_handle_t handle, uint8_t phy_addr, uint8_t reg_addr, uint16_t data);
+
+/**
+  \brief       Control Ethernet Interface.
+  \param[in]   handle  ethernet handle
+  \param[in]   control  Operation
+  \param[in]   arg      Argument of operation (optional)
+  \return      error code
+*/
+int32_t cvi_eth_mac_control(eth_mac_handle_t handle, uint32_t control, uint32_t arg);
+/**
+  \brief       Get Ethernet MAC Address.
+  \param[in]   handle  ethernet handle
+  \param[in]   mac  Pointer to address
+  \return      error code
+*/
+int32_t cvi_eth_mac_get_macaddr(eth_mac_handle_t handle, eth_mac_addr_t *mac);
+
+/**
+  \brief       Set Ethernet MAC Address.
+  \param[in]   handle  ethernet handle
+  \param[in]   mac  Pointer to address
+  \return      error code
+*/
+int32_t cvi_eth_mac_set_macaddr(eth_mac_handle_t handle, const eth_mac_addr_t *mac);
+
+/**
+  \brief       Connect phy device to mac device.
+  \param[in]   handle_mac  mac handle
+  \param[in]   handle_phy  phy handle
+*/
+void dw_eth_mac_connect_phy(eth_mac_handle_t handle_mac, eth_phy_handle_t handle_phy);
+
+/**
+  \brief       Read Ethernet PHY Register through Management Interface.
+  \param[in]   handle  ethernet handle
+  \param[in]   phy_addr  5-bit device address
+  \param[in]   reg_addr  5-bit register address
+  \param[out]  data      Pointer where the result is written to
+  \return      error code
+*/
+int32_t dw_eth_mac_phy_read(eth_mac_handle_t handle, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data);
+
+/**
+  \brief       Send Ethernet frame.
+  \param[in]   handle  ethernet handle
+  \param[in]   frame  Pointer to frame buffer with data to send
+  \param[in]   len    Frame buffer length in bytes
+  \return      error code
+*/
+int32_t cvi_eth_mac_send_frame(eth_mac_handle_t handle, const uint8_t *frame, uint32_t len);
+
+/**
+  \brief       Read data of received Ethernet frame.
+  \param[in]   handle  ethernet handle
+  \param[in]   frame  Pointer to frame buffer for data to read into
+  \param[in]   len    Frame buffer length in bytes
+  \return      number of data bytes read or execution status
+                 - value >= 0: number of data bytes read
+                 - value < 0: error occurred, value is execution status as defined with execution_status
+*/
+int32_t cvi_eth_mac_read_frame(eth_mac_handle_t handle, uint8_t *frame, uint32_t len);
+
+/**
+  \brief       This function is used to initialize Ethernet device and register an event callback.
+  \param[in]   idx device id
+  \param[in]   cb  callback to handle ethernet event
+  \return      return ethernet handle if success
+ */
+eth_mac_handle_t cvi_eth_mac_init(unsigned int *base);
 
 #ifdef __cplusplus
 }

+ 15 - 12
bsp/cvitek/drivers/libraries/eth/eth_phy_cvitek.c

@@ -1,18 +1,26 @@
 /*
-* Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
-*/
+ * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 #include <stdio.h>
 #include <assert.h>
 #include <string.h>
 #include <stdbool.h>
 
-// #include <mmio.h>
-
 #include "cvi_eth_phy.h"
 #include "mii.h"
 
-
-
 // #define CVI_ETH_PHY_LOOPBACK
 #define LOOPBACK_XMII2MAC       0x8000
 #define LOOPBACK_PCS2MAC        0x2000
@@ -334,14 +342,9 @@ int32_t cv181x_start(eth_phy_handle_t handle)
     assert(handle);
 
     eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
-    int32_t ret;
 
     /* Read the Status (2x to make sure link is right) */
-    ret = genphy_update_link(dev);
-
-    if (ret) {
-        return ret;
-    }
+    genphy_update_link(dev);
 
     return cv181x_parse_status(dev);
 }