You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2022/03/15 13:23:33 UTC

[GitHub] [incubator-nuttx] jlaitine commented on a change in pull request #5740: Add ethernet support for risc-v/MPFS

jlaitine commented on a change in pull request #5740:
URL: https://github.com/apache/incubator-nuttx/pull/5740#discussion_r826966650



##########
File path: arch/risc-v/src/mpfs/mpfs_ethernet.c
##########
@@ -0,0 +1,3855 @@
+/****************************************************************************
+ * arch/risc-v/src/mpfs/mpfs_ethernet.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+#include <queue.h>
+#include <errno.h>
+
+#include <arpa/inet.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/wdog.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/net/mii.h>
+#include <nuttx/net/gmii.h>
+#include <nuttx/net/arp.h>
+#include <nuttx/net/netdev.h>
+
+#ifdef CONFIG_NET_PKT
+#  include <nuttx/net/pkt.h>
+#endif
+
+#include "riscv_internal.h"
+#include "hardware/mpfs_ethernet.h"
+#include "mpfs_memorymap.h"
+
+#if defined(CONFIG_NET) && defined(CONFIG_MPFS_ETHMAC)
+
+#ifndef OK
+#  define OK 0
+#endif
+
+#define MPFS_PMPCFG_ETH0_0   (MPFS_MPUCFG_BASE + 0x400)
+#define MPFS_PMPCFG_ETH0_1   (MPFS_MPUCFG_BASE + 0x408)
+#define MPFS_PMPCFG_ETH0_2   (MPFS_MPUCFG_BASE + 0x410)
+#define MPFS_PMPCFG_ETH0_3   (MPFS_MPUCFG_BASE + 0x418)
+#define MPFS_PMPCFG_ETH1_0   (MPFS_MPUCFG_BASE + 0x500)
+#define MPFS_PMPCFG_ETH1_1   (MPFS_MPUCFG_BASE + 0x508)
+#define MPFS_PMPCFG_ETH1_2   (MPFS_MPUCFG_BASE + 0x510)
+#define MPFS_PMPCFG_ETH1_3   (MPFS_MPUCFG_BASE + 0x518)
+
+#if defined(CONFIG_MPFS_ETHMAC_0) && defined(CONFIG_MPFS_ETHMAC_1)
+#  warning "Using 2 MACs is not yet supported."
+#  define MPFS_NETHERNET     (2)
+#else
+#  define MPFS_NETHERNET     (1)
+#endif
+
+#define MPFS_MAC_QUEUE_COUNT (4)
+
+#if !defined(CONFIG_SCHED_WORKQUEUE)
+#  error Work queue support is required
+#else
+
+/* Select work queue */
+
+#  if defined(CONFIG_MPFS_ETHMAC_HPWORK)
+#    define ETHWORK HPWORK
+#  elif defined(CONFIG_MPFS_ETHMAC_LPWORK)
+#    define ETHWORK LPWORK
+#  else
+#    define ETHWORK LPWORK
+#  endif
+#endif
+
+#ifndef CONFIG_MPFS_PHYADDR
+#  error "CONFIG_MPFS_PHYADDR must be defined in the NuttX configuration"
+#endif
+
+#if !defined(CONFIG_MPFS_MAC_SGMII) && !defined(CONFIG_MPFS_MAC_GMII)
+#  warning "Neither CONFIG_MPFS_MAC_SGMII nor CONFIG_MPFS_MAC_GMII defined"
+#endif
+
+#if defined(CONFIG_MPFS_MAC_SGMII) && defined(CONFIG_MPFS_MAC_GMII)
+#  error "Both CONFIG_MPFS_MAC_SGMII and CONFIG_MPFS_MAC_GMII defined"
+#endif
+
+/* Number of buffers for RX */
+
+#ifndef CONFIG_MPFS_ETHMAC_NRXBUFFERS
+#  define CONFIG_MPFS_ETHMAC_NRXBUFFERS  (16)
+#endif
+
+/* Number of buffers for TX */
+
+#ifndef CONFIG_MPFS_ETHMAC_NTXBUFFERS
+#  define CONFIG_MPFS_ETHMAC_NTXBUFFERS  (8)
+#endif
+
+/* GMAC buffer sizes
+ * REVISIT: do we want to make GMAC_RX_UNITSIZE configurable?
+ * issue when using the MTU size receive block
+ */
+
+#define GMAC_RX_UNITSIZE  (512)                  /* Fixed size for RX buffer */
+#define GMAC_TX_UNITSIZE  CONFIG_NET_ETH_PKTSIZE /* MAX size for Ethernet packet */
+
+/* The MAC can support frame lengths up to 1536 bytes */
+
+#define GMAC_MAX_FRAMELEN (1536)
+#if CONFIG_NET_ETH_PKTSIZE > GMAC_MAX_FRAMELEN
+#  error CONFIG_NET_ETH_PKTSIZE is too large
+#endif
+
+/* for DMA dma_rxbuf_size */
+
+#define MPFS_MAC_RX_BUF_VALUE ((GMAC_RX_UNITSIZE + 63) / 64)
+
+/* We need at least one more free buffer than transmit buffers */
+
+#define MPFS_GMAC_NFREEBUFFERS (CONFIG_MPFS_ETHMAC_NTXBUFFERS + 1)
+
+#ifdef CONFIG_NET_DUMPPACKET
+#  define mpfs_dumppacket(m,a,n) lib_dumpbuffer(m,a,n)
+#else
+#  define mpfs_dumppacket(m,a,n)
+#endif
+
+#ifdef CONFIG_MPFS_HAVE_CORERMII
+#  define CORE_RMII_RESET       (1 << 15)
+#  define CORE_RMII_LOOPBACK    (1 << 2)
+#  define CORE_RMII_FULL_DUPLEX (1 << 1)
+#  define CORE_RMII_100MBIT     (1 << 0)
+#endif
+
+/* Timing *******************************************************************/
+
+/* TX poll delay = 1 seconds.
+ * CLK_TCK is the number of clock ticks per second
+ */
+
+#define MPFS_WDDELAY     (1 * CLK_TCK)
+
+/* TX timeout = 1 minute */
+
+#define MPFS_TXTIMEOUT   (60 * CLK_TCK)
+
+/* PHY reset tim in loop counts */
+
+#define PHY_RESET_WAIT_COUNT (10)
+
+/* PHY re-try coount in loop counts */
+
+#define PHY_RETRY_MAX   300000
+
+/* This is a helper pointer for accessing the contents of the GMAC header */
+
+#define BUF ((struct eth_hdr_s *)priv->dev.d_buf)
+
+#define upper_32_bits(n) ((uint32_t)(((n) >> 16) >> 16))
+#define lower_32_bits(n) ((uint32_t)(n))
+
+/* Interrupt flags */
+
+#define INT_RX     (GEM_INT_RECEIVE_COMPLETE)
+#define INT_TX     (GEM_INT_TRANSMIT_COMPLETE)
+#define INT_ERRORS (GEM_INT_TRANSMIT_BUFFER_UNDERRUN | \
+                    GEM_INT_RECEIVE_OVERRUN | \
+                    GEM_INT_AMBA_ERROR | GEM_INT_RESP_NOT_OK)
+#define INT_ALL    (INT_RX | INT_TX | INT_ERRORS)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct gmac_rxdesc_s
+{
+    uint32_t addr;     /* Buffer address */
+    uint32_t status;   /* RX status and controls */
+#if defined(CONFIG_MPFS_ETHMAC_64BIT_ADDRESS_MODE)
+    uint32_t addr_hi;  /* Buffer address high 32-bits */
+    uint32_t unused;
+#endif
+};
+
+/* Transmit buffer descriptor */
+
+struct gmac_txdesc_s
+{
+    uint32_t addr;     /* Buffer address */
+    uint32_t status;   /* TX status and controls */
+#if defined(CONFIG_MPFS_ETHMAC_64BIT_ADDRESS_MODE)
+    uint32_t addr_hi;  /* Buffer address high 32-bits */
+    uint32_t unused;   /*  */
+#endif
+};
+
+static uint8_t g_pktbuf[MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE];
+
+#if defined(CONFIG_MPFS_GMAC_PREALLOCATE)
+static uint8_t g_txbuffer[CONFIG_MPFS_ETHMAC_NTXBUFFERS * GMAC_TX_UNITSIZE]
+               aligned_data(8);
+static uint8_t g_rxbuffer[CONFIG_MPFS_ETHMAC_NRXBUFFERS * GMAC_RX_UNITSIZE]
+               aligned_data(8);
+#endif
+
+struct mpfs_mac_queue_s
+{
+#if defined(CONFIG_MPFS_GMAC_PREALLOCATE)
+        struct gmac_txdesc_s  tx_desc_tab[CONFIG_MPFS_ETHMAC_NTXBUFFERS];  /* Transmit descriptor table */
+        struct gmac_rxdesc_s  rx_desc_tab[CONFIG_MPFS_ETHMAC_NRXBUFFERS];  /* Receive descriptor table */
+#else
+        struct gmac_txdesc_s  *tx_desc_tab;     /* Transmit descriptor table */
+        struct gmac_rxdesc_s  *rx_desc_tab;     /* Receive descriptor table */
+        uint8_t               *rxbuffer;        /* Allocated RX buffers */
+        uint8_t               *txbuffer;        /* Allocated TX buffers */
+#endif
+        uint32_t              txhead;           /* Circular buffer head index */
+        uint32_t              txtail;           /* Circular buffer tail index */
+        uint32_t              rxndx;            /* RX index for current processing RX descriptor */
+        volatile uint32_t     *int_status;      /* interrupt status */
+        volatile uint32_t     *int_mask;        /* interrupt mask */
+        volatile uint32_t     *int_enable;      /* interrupt enable */
+        volatile uint32_t     *int_disable;     /* interrupt disable */
+        volatile uint32_t     *rx_q_ptr;        /* RX queue pointer */
+        volatile uint32_t     *tx_q_ptr;        /* TX queue pointer */
+        volatile uint32_t     *dma_rxbuf_size;  /* RX queue buffer size */
+};
+
+/* The mpfs_ethmac_s encapsulates all state information for a single
+ * hardware interface
+ */
+
+struct mpfs_ethmac_s
+{
+  uintptr_t     regbase;                         /* mac base address */
+  irq_t         mac_q_int[MPFS_MAC_QUEUE_COUNT]; /* irq numbers */
+  uint8_t       ifup : 1;                        /* true:ifup false:ifdown */
+  uint8_t       intf;                            /* Ethernet interface number */
+  uint8_t       phyaddr;                         /* PHY address */
+  struct wdog_s txpoll;                          /* TX poll timer */
+  struct wdog_s txtimeout;                       /* TX timeout timer */
+  struct work_s irqwork;                         /* For deferring interrupt work to the work queue */
+  struct work_s pollwork;                        /* For deferring poll work to the work queue */
+
+  /* This holds the information visible to the NuttX network */
+
+  struct net_driver_s     dev;  /* Interface understood by the network */
+  struct mpfs_mac_queue_s queue[MPFS_MAC_QUEUE_COUNT];
+};
+
+/* These are the pre-allocated Ethernet device structures */
+
+static struct mpfs_ethmac_s g_mpfsethmac[MPFS_NETHERNET];
+
+static uintptr_t g_regbases[MPFS_NETHERNET] =
+{
+#ifdef CONFIG_MPFS_ETHMAC_0
+  MPFS_GEM0_LO_BASE,
+#endif
+#ifdef CONFIG_MPFS_ETHMAC_1
+  MPFS_GEM1_LO_BASE,
+#endif
+  /* if support for emacs is added later
+   * (MPFS_GEM0_LO_BASE + 0x1000),
+   * (MPFS_GEM1_LO_BASE + 0x1000),'
+   */
+};
+
+static const irq_t g_irq_numbers[MPFS_NETHERNET][MPFS_MAC_QUEUE_COUNT] =
+{
+#ifdef CONFIG_MPFS_ETHMAC_0
+  { MPFS_IRQ_MAC0_INT, MPFS_IRQ_MAC0_QUEUE1,
+    MPFS_IRQ_MAC0_QUEUE2, MPFS_IRQ_MAC0_QUEUE3 },
+#endif
+#ifdef CONFIG_MPFS_ETHMAC_1
+  { MPFS_IRQ_MAC1_INT, MPFS_IRQ_MAC1_QUEUE1,
+    MPFS_IRQ_MAC1_QUEUE2, MPFS_IRQ_MAC1_QUEUE3 },
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Register operations ******************************************************/
+
+static uint16_t mpfs_txinuse(struct mpfs_ethmac_s *priv, unsigned int queue);
+static uint16_t mpfs_txfree(struct mpfs_ethmac_s *priv, unsigned int queue);
+static int mpfs_buffer_initialize(struct mpfs_ethmac_s *priv,
+                                  unsigned int queue);
+static void mpfs_buffer_free(struct mpfs_ethmac_s *priv, unsigned int queue);
+
+static void mpfs_poll_expiry(wdparm_t arg);
+static void mpfs_poll_work(void *arg);
+
+static int  mpfs_transmit(struct mpfs_ethmac_s *priv, unsigned int queue);
+static int  mpfs_txpoll(struct net_driver_s *dev);
+static void mpfs_dopoll(struct mpfs_ethmac_s *priv);
+
+/* NuttX callback functions */
+
+static int  mpfs_ifup(struct net_driver_s *dev);
+static int  mpfs_ifdown(struct net_driver_s *dev);
+
+static void mpfs_txavail_work(void *arg);
+static int  mpfs_txavail(struct net_driver_s *dev);
+
+#ifdef CONFIG_NETDEV_PHY_IOCTL
+static int  mpfs_ioctl(struct net_driver_s *dev, int cmd,
+                       unsigned long arg);
+#endif
+
+#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6)
+static unsigned int mpfs_hashindx(const uint8_t *mac);
+static int  mpfs_addmac(struct net_driver_s *dev, const uint8_t *mac);
+#endif
+#ifdef CONFIG_NET_MCASTGROUP
+static int mpfs_rmmac(struct net_driver_s *dev, const uint8_t *mac);
+#endif
+
+#ifdef CONFIG_NETDEV_IOCTL
+static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg);
+#endif
+
+/* PHY Initialization */
+
+static void mpfs_enablemdio(struct mpfs_ethmac_s *priv);
+static void mpfs_disablemdio(struct mpfs_ethmac_s *priv);
+static int  mpfs_phyreset(struct mpfs_ethmac_s *priv);
+static int  mpfs_phyinit(struct mpfs_ethmac_s *priv);
+static int  mpfs_phyread(struct mpfs_ethmac_s *priv, uint8_t phyaddr,
+                         uint8_t regaddr, uint16_t *phyval);
+static int  mpfs_phywrite(struct mpfs_ethmac_s *priv, uint8_t phyaddr,
+                          uint8_t regaddr, uint16_t phyval);
+static int  mpfs_phywait(struct mpfs_ethmac_s *priv);
+static int  mpfs_phyfind(struct mpfs_ethmac_s *priv, uint8_t *phyaddr);
+#ifdef CONFIG_MPFS_MAC_AUTONEG
+static int  mpfs_autonegotiate(struct mpfs_ethmac_s *priv);
+#else
+static void mpfs_linkspeed(struct mpfs_ethmac_s *priv);
+#endif
+
+#if defined(CONFIG_DEBUG_NET) && defined(CONFIG_DEBUG_INFO)
+static void mpfs_phydump(struct mpfs_ethmac_s *priv);
+#else
+#  define mpfs_phydump(priv)
+#endif
+
+/* MAC/DMA Initialization */
+
+static void mpfs_txreset(struct mpfs_ethmac_s *priv);
+static void mpfs_rxreset(struct mpfs_ethmac_s *priv);
+static int  mpfs_macenable(struct mpfs_ethmac_s *priv);
+static int  mpfs_ethconfig(struct mpfs_ethmac_s *priv);
+static void mpfs_ethreset(struct mpfs_ethmac_s *priv);
+#ifdef CONFIG_NET_ICMPv6
+static void mpfs_ipv6multicast(struct sam_gmac_s *priv);
+#endif
+
+static void mpfs_interrupt_work(void *arg);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mac_putreg
+ *
+ * Description:
+ *  Write a value to an MAC register
+ *
+ * Input Parameters:
+ *   val - The value to write to the register
+ *   offset - The mac register address offset to write
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static inline void mac_putreg(struct mpfs_ethmac_s *priv,
+                              uint32_t offset, uint32_t val)
+{
+  uint32_t *addr = (uint32_t *)priv->regbase + offset;

Review comment:
       ```suggestion
     uint32_t *addr = (uint32_t *)(priv->regbase + offset);
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org