[U-Boot] [PATCH 1/2 v2] drivers: net: add NXP ENETC ethernet driver

Bin Meng bmeng.cn at gmail.com
Mon Jun 10 03:42:43 UTC 2019


Hi Alex,

On Sat, Jun 8, 2019 at 12:12 AM Alex Marginean <alexm.osslist at gmail.com> wrote:
>
> Adds a driver for NXP ENETC ethernet controller currently integrated in
> LS1028a.  ENETC is a fairly straight-forward BD ring device and interfaces
> are presented as PCI EPs on the SoC ECAM.
>
> Signed-off-by: Catalin Horghidan <catalin.horghidan at nxp.com>
> Signed-off-by: Alex Marginean <alexm.osslist at gmail.com>
> ---
>
> Changes in v2:
>         - Added SXGMII MAC configuration
>         - simplified naming code in _bind
>         - renamed ENETC_DBG to enetc_dbg and make it use debug()
>         - replaced a couple of magic numbers with macros
>         - droped _V1 from PCI ID macro
>         - several styling and cosmetic updates to the header file
>
>  configs/ls1028aqds_tfa_defconfig |   1 +
>  configs/ls1028ardb_tfa_defconfig |   1 +
>  drivers/net/Kconfig              |   7 +
>  drivers/net/Makefile             |   1 +
>  drivers/net/fsl_enetc.c          | 344 +++++++++++++++++++++++++++++++
>  drivers/net/fsl_enetc.h          | 172 ++++++++++++++++
>  include/pci_ids.h                |   1 +
>  7 files changed, 527 insertions(+)
>  create mode 100644 drivers/net/fsl_enetc.c
>  create mode 100644 drivers/net/fsl_enetc.h
>
> diff --git a/configs/ls1028aqds_tfa_defconfig b/configs/ls1028aqds_tfa_defconfig
> index 7982ce4157..11fe344b04 100644
> --- a/configs/ls1028aqds_tfa_defconfig
> +++ b/configs/ls1028aqds_tfa_defconfig
> @@ -45,6 +45,7 @@ CONFIG_PHY_ATHEROS=y
>  CONFIG_DM_ETH=y
>  CONFIG_PHY_GIGE=y
>  CONFIG_E1000=y
> +CONFIG_FSL_ENETC=y

This, along with mdio changes to the defconfig files in the patch
[2/2], should be in a separate patch, and come in the last commit in
this series.

>  CONFIG_PCI=y
>  CONFIG_DM_PCI=y
>  CONFIG_DM_PCI_COMPAT=y
> diff --git a/configs/ls1028ardb_tfa_defconfig b/configs/ls1028ardb_tfa_defconfig
> index c65e37df79..ab6f2a850c 100644
> --- a/configs/ls1028ardb_tfa_defconfig
> +++ b/configs/ls1028ardb_tfa_defconfig
> @@ -45,6 +45,7 @@ CONFIG_PHY_ATHEROS=y
>  CONFIG_DM_ETH=y
>  CONFIG_PHY_GIGE=y
>  CONFIG_E1000=y
> +CONFIG_FSL_ENETC=y

ditto.

>  CONFIG_PCI=y
>  CONFIG_DM_PCI=y
>  CONFIG_DM_PCI_COMPAT=y
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 635f8d72c2..1fe038b859 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -566,4 +566,11 @@ config HIGMACV300_ETH
>           This driver supports HIGMACV300 Ethernet controller found on
>           HiSilicon SoCs.
>
> +config FSL_ENETC
> +       bool "NXP ENETC Ethernet controller"
> +       depends on DM_PCI && DM_ETH
> +       help
> +         This driver supports the NXP ENETC Ethernet controller found on some
> +         of the NXP SoCs.
> +
>  endif # NETDEVICES
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 40038427db..c08dc2e20c 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -78,3 +78,4 @@ obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
>  obj-y += mscc_eswitch/
>  obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
>  obj-$(CONFIG_MDIO_SANDBOX) += mdio_sandbox.o
> +obj-$(CONFIG_FSL_ENETC) += fsl_enetc.o
> diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c
> new file mode 100644
> index 0000000000..325e032746
> --- /dev/null
> +++ b/drivers/net/fsl_enetc.c
> @@ -0,0 +1,344 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * ENETC ethernet controller driver
> + * Copyright 2017-2019 NXP
> + */
> +
> +#include "fsl_enetc.h"

nits: this local include should come after all other includes.

> +
> +#include <dm.h>
> +#include <errno.h>
> +#include <memalign.h>
> +#include <asm/io.h>
> +#include <asm/processor.h>
> +#include <pci.h>
> +
> +static int enetc_bind(struct udevice *dev)
> +{
> +       char name[16];
> +
> +       sprintf(name, "enetc#%u", PCI_FUNC(dm_pci_get_bdf(dev)));
> +       device_set_name(dev, name);
> +
> +       return 0;
> +}
> +
> +/*
> + * Probe ENETC driver:
> + * - initialize port and station interface BARs
> + */
> +static int enetc_probe(struct udevice *dev)
> +{
> +       struct enetc_devfn *hw = dev_get_priv(dev);
> +       int err = 0;
> +
> +       if (ofnode_valid(dev->node) && !ofnode_is_available(dev->node)) {
> +               enetc_dbg(dev, "interface disabled\n");
> +               return -ENODEV;
> +       }
> +
> +       /* initialize register */
> +       hw->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
> +       if (!hw->regs_base) {
> +               enetc_dbg(dev, "failed to map BAR0\n");
> +               return -EINVAL;
> +       }
> +       hw->port_regs = hw->regs_base + ENETC_PORT_REGS_OFF;
> +
> +       dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);
> +
> +       return err;
> +}
> +
> +/* ENETC Port MAC address registers accept big-endian format */
> +static void enetc_set_primary_mac_addr(struct enetc_devfn *hw, const u8 *addr)
> +{
> +       u16 lower = *(const u16 *)(addr + 4);
> +       u32 upper = *(const u32 *)addr;
> +
> +       enetc_write_port(hw, ENETC_PSIPMAR0, upper);
> +       enetc_write_port(hw, ENETC_PSIPMAR1, lower);
> +}
> +
> +int enetc_enable_si_port(struct enetc_devfn *hw)

nits: this should be static. Can we put a single line comment to
describe what this function does, like others?

> +{
> +       u32 val;
> +
> +       /* set Rx/Tx BDR count */
> +       val = ENETC_PSICFGR_SET_TXBDR(ENETC_TX_BDR_CNT);
> +       val |= ENETC_PSICFGR_SET_RXBDR(ENETC_RX_BDR_CNT);
> +       enetc_write_port(hw, ENETC_PSICFGR(0), val);
> +       /* set Rx max frame size */
> +       enetc_write_port(hw, ENETC_PM_MAXFRM, ENETC_RX_MAXFRM_SIZE);
> +       /* enable MAC port */
> +       enetc_write_port(hw, ENETC_PM_CC, ENETC_PM_CC_RX_TX_EN);
> +       /* enable port */
> +       enetc_write_port(hw, ENETC_PMR, ENETC_PMR_SI0_EN);
> +       /* set SI cache policy */
> +       enetc_write(hw, ENETC_SICAR0, ENETC_SICAR_RD_CFG | ENETC_SICAR_WR_CFG);
> +       /* enable SI */
> +       enetc_write(hw, ENETC_SIMR, ENETC_SIMR_EN);
> +
> +       return 0;
> +}
> +
> +/* Use a single set of BDs and buffers.  It's functionally OK as u-boot doesn't
> + * use multiple interfaces at once.

Yep this is true for U-Boot, however it's not a good practice. Could
you please move these to the "struct enetc_devfn"?

> + */
> +DEFINE_ALIGN_BUFFER(struct enetc_tx_bd, enetc_txbd, ENETC_BD_CNT, ENETC_ALIGN);
> +DEFINE_ALIGN_BUFFER(union enetc_rx_bd, enetc_rxbd, ENETC_BD_CNT, ENETC_ALIGN);
> +DEFINE_ALIGN_BUFFER(u8, enetc_rx_buff, ENETC_RX_MBUFF_SIZE, ENETC_ALIGN);

For the rx buffer, isn't the one provided by U-Boot does not fit the
hardware requirement, so we have to create our own rx buffer?

> +
> +static inline u64 enetc_rxb_address(struct udevice *dev, int i)
> +{
> +       int off = i * ENETC_RX_MAXFRM_SIZE;
> +
> +       return cpu_to_le64(dm_pci_virt_to_mem(dev, enetc_rx_buff + off));
> +}
> +
> +/**
> + * Setup a single Tx BD Ring (ID = 0):
> + * - set Tx buffer descriptor address
> + * - set the BD count
> + * - initialize the producer and consumer index
> + */
> +static void enetc_setup_tx_bdr(struct enetc_devfn *hw)
> +{
> +       struct bd_ring *tx_bdr = &hw->tx_bdr;
> +       u64 tx_bd_add = (u64)enetc_txbd;
> +
> +       /* used later to advance to the next Tx BD */
> +       tx_bdr->bd_count = ENETC_BD_CNT;
> +       tx_bdr->next_prod_idx = 0;
> +       tx_bdr->next_cons_idx = 0;
> +       tx_bdr->cons_idx = hw->regs_base +
> +                               ENETC_BDR(TX, ENETC_TX_BDR_ID, ENETC_TBCIR);
> +       tx_bdr->prod_idx = hw->regs_base +
> +                               ENETC_BDR(TX, ENETC_TX_BDR_ID, ENETC_TBPIR);
> +
> +       /* set Tx BD address */
> +       enetc_bdr_write(hw, TX, ENETC_TX_BDR_ID, ENETC_TBBAR0,
> +                       lower_32_bits(tx_bd_add));
> +       enetc_bdr_write(hw, TX, ENETC_TX_BDR_ID, ENETC_TBBAR1,
> +                       upper_32_bits(tx_bd_add));
> +       /* set Tx 8 BD count */
> +       enetc_bdr_write(hw, TX, ENETC_TX_BDR_ID, ENETC_TBLENR,
> +                       tx_bdr->bd_count);
> +
> +       /* reset both producer/consumer indexes */
> +       enetc_write_reg(tx_bdr->cons_idx, tx_bdr->next_cons_idx);
> +       enetc_write_reg(tx_bdr->prod_idx, tx_bdr->next_prod_idx);
> +
> +       /* enable TX ring */
> +       enetc_bdr_write(hw, TX, ENETC_TX_BDR_ID, ENETC_TBMR, ENETC_TBMR_EN);
> +}
> +
> +/**
> + * Setup a single Rx BD Ring (ID = 0):
> + * - set Rx buffer descriptors address (one descriptor per buffer)
> + * - set buffer size as max frame size
> + * - enable Rx ring
> + * - reset consumer and producer indexes
> + * - set buffer for each descriptor
> + */
> +static void enetc_setup_rx_bdr(struct udevice *dev, struct enetc_devfn *hw)
> +{
> +       struct bd_ring *rx_bdr = &hw->rx_bdr;
> +       u64 rx_bd_add = (u64)enetc_rxbd;
> +       int i;
> +
> +       /* used later to advance to the next BD produced by ENETC HW */
> +       rx_bdr->bd_count = ENETC_BD_CNT;
> +       rx_bdr->next_prod_idx = 0;
> +       rx_bdr->next_cons_idx = 0;
> +       rx_bdr->cons_idx = hw->regs_base +
> +                               ENETC_BDR(RX, ENETC_RX_BDR_ID, ENETC_RBCIR);
> +       rx_bdr->prod_idx = hw->regs_base +
> +                               ENETC_BDR(RX, ENETC_RX_BDR_ID, ENETC_RBPIR);
> +
> +       /* set Rx BD address */
> +       enetc_bdr_write(hw, RX, ENETC_RX_BDR_ID, ENETC_RBBAR0,
> +                       lower_32_bits(rx_bd_add));
> +       enetc_bdr_write(hw, RX, ENETC_RX_BDR_ID, ENETC_RBBAR1,
> +                       upper_32_bits(rx_bd_add));
> +       /* set Rx BD count (multiple of 8) */
> +       enetc_bdr_write(hw, RX, ENETC_RX_BDR_ID, ENETC_RBLENR,
> +                       rx_bdr->bd_count);
> +       /* set Rx buffer  size */
> +       enetc_bdr_write(hw, RX, ENETC_RX_BDR_ID, ENETC_RBBSR, ENETC_BUFF_SIZE);
> +
> +       /* fill Rx BD */
> +       memset(enetc_rxbd, 0, rx_bdr->bd_count * sizeof(union enetc_rx_bd));
> +       for (i = 0; i < rx_bdr->bd_count; i++) {
> +               enetc_rxbd[i].w.addr = enetc_rxb_address(dev, i);
> +               /* each RX buffer must be aligned to 64B */
> +               WARN_ON(enetc_rxbd[i].w.addr & (ENETC_ALIGN - 1));
> +       }
> +
> +       /* reset producer (ENETC owned) and consumer (SW owned) index */
> +       enetc_write_reg(rx_bdr->cons_idx, rx_bdr->next_cons_idx);
> +       enetc_write_reg(rx_bdr->prod_idx, rx_bdr->next_prod_idx);
> +
> +       /* enable Rx ring */
> +       enetc_bdr_write(hw, RX, ENETC_RX_BDR_ID, ENETC_RBMR, ENETC_RBMR_EN);
> +}
> +
> +/**
> + * Start ENETC interface:
> + * - perform FLR
> + * - enable access to port and SI registers
> + * - set mac address
> + * - setup TX/RX buffer descriptors
> + * - enable Tx/Rx rings
> + */
> +static int enetc_start(struct udevice *dev)
> +{
> +       struct eth_pdata *plat = dev_get_platdata(dev);
> +       struct enetc_devfn *hw = dev_get_priv(dev);
> +       u32 if_mode;
> +
> +       /* reset and enable the PCI device */
> +       dm_pci_flr(dev);
> +       dm_pci_clrset_config16(dev, PCI_COMMAND, 0,
> +                              PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> +
> +       if_mode = enetc_read_port(hw, ENETC_PM_IF_MODE);
> +
> +       if (enetc_read_port(hw, ENETC_G_EPFBLPR) & ENETC_G_EPFBLPR1_XGMII)
> +               if_mode &= ~ENETC_PM_IF_IFMODE_MASK;
> +       else if (if_mode & ENETC_PM_IF_MODE_RG)
> +               if_mode |= ENETC_PM_IF_MODE_AN_ENA;
> +
> +       enetc_write_port(hw, ENETC_PM_IF_MODE, if_mode);
> +
> +       if (!is_valid_ethaddr(plat->enetaddr)) {
> +               enetc_dbg(dev, "invalid MAC address, generate random ...\n");
> +               net_random_ethaddr(plat->enetaddr);
> +       }
> +       enetc_set_primary_mac_addr(hw, plat->enetaddr);
> +
> +       enetc_enable_si_port(hw);
> +
> +       /* setup Tx/Rx buffer descriptors */
> +       enetc_setup_tx_bdr(hw);
> +       enetc_setup_rx_bdr(dev, hw);
> +
> +       return 0;
> +}
> +
> +static void enetc_stop(struct udevice *dev)
> +{
> +       /* FLR is sufficient to quiesce the device */
> +       dm_pci_flr(dev);
> +}
> +
> +/**
> + * ENETC transmit packet:
> + * - check if Tx BD ring is full
> + * - set buffer/packet address (dma address)
> + * - set final fragment flag
> + * - try while producer index equals consumer index or timeout
> + */
> +static int enetc_send(struct udevice *dev, void *packet, int length)
> +{
> +       struct enetc_devfn *hw = dev_get_priv(dev);
> +       struct bd_ring *txr = &hw->tx_bdr;
> +       void *nv_packet = (void *)packet;
> +       int tries = ENETC_POLL_TRIES;
> +       u32 pi, ci;
> +
> +       pi = txr->next_prod_idx;
> +       ci = enetc_read_reg(txr->cons_idx) & ENETC_BDR_IDX_MASK;
> +       /* Tx ring is full when */
> +       if (((pi + 1) % txr->bd_count) == ci) {
> +               enetc_dbg(dev, "Tx BDR full\n");
> +               return -ETIMEDOUT;
> +       }
> +       enetc_dbg(dev, "TxBD[%d]send: pkt_len=%d, buff @0x%x%08x\n", pi, length,
> +                 upper_32_bits((u64)nv_packet), lower_32_bits((u64)nv_packet));
> +
> +       /* prepare Tx BD */
> +       memset(&enetc_txbd[pi], 0x0, sizeof(struct enetc_tx_bd));
> +       enetc_txbd[pi].addr =  cpu_to_le64(dm_pci_virt_to_mem(dev, nv_packet));
> +       enetc_txbd[pi].buf_len = cpu_to_le16(length);
> +       enetc_txbd[pi].frm_len = cpu_to_le16(length);
> +       enetc_txbd[pi].flags = cpu_to_le16(ENETC_TXBD_FLAGS_F);
> +       dmb();
> +       /* send frame: increment producer index */
> +       pi = (pi + 1) % txr->bd_count;
> +       txr->next_prod_idx = pi;
> +       enetc_write_reg(txr->prod_idx, pi);
> +       while ((--tries >= 0) &&
> +              (pi != (enetc_read_reg(txr->cons_idx) & ENETC_BDR_IDX_MASK)))
> +               udelay(10);
> +
> +       return tries > 0 ? 0 : -ETIMEDOUT;
> +}
> +
> +/**
> + * Handles frame receive and cleans up the BD slot on the Rx ring.
> + */
> +static int enetc_recv(struct udevice *dev, int flags, uchar **packetp)
> +{
> +       struct enetc_devfn *hw = dev_get_priv(dev);
> +       struct bd_ring *rxr = &hw->rx_bdr;
> +       int tries = ENETC_POLL_TRIES;
> +       int pi = rxr->next_prod_idx;
> +       int ci = rxr->next_cons_idx;
> +       u32 status;
> +       int len;
> +       u8 rdy;
> +
> +       do {
> +               dmb();
> +               status = le32_to_cpu(enetc_rxbd[pi].r.lstatus);
> +               /* check if current BD is ready to be consumed */
> +               rdy = ENETC_RXBD_STATUS_R(status);
> +       } while (--tries >= 0 && !rdy);
> +
> +       if (!rdy)
> +               return -EAGAIN;
> +
> +       dmb();
> +       len = le16_to_cpu(enetc_rxbd[pi].r.buf_len);
> +       *packetp = (uchar *)enetc_rxb_address(dev, pi);
> +       enetc_dbg(dev, "RxBD[%d]: len=%d err=%d pkt=0x%x%08x\n", pi, len,
> +                 ENETC_RXBD_STATUS_ERRORS(status),
> +                 upper_32_bits((u64)*packetp), lower_32_bits((u64)*packetp));
> +
> +       /* BD clean up and advance to next in ring */
> +       memset(&enetc_rxbd[pi], 0, sizeof(union enetc_rx_bd));
> +       enetc_rxbd[pi].w.addr = enetc_rxb_address(dev, pi);
> +       rxr->next_prod_idx = (pi + 1) % rxr->bd_count;
> +       ci = (ci + 1) % rxr->bd_count;
> +       rxr->next_cons_idx = ci;
> +       dmb();
> +       /* free up the slot in the ring for HW */
> +       enetc_write_reg(rxr->cons_idx, ci);
> +
> +       return len;
> +}
> +
> +static const struct eth_ops enetc_ops = {
> +       .start  = enetc_start,
> +       .send   = enetc_send,
> +       .recv   = enetc_recv,
> +       .stop   = enetc_stop,
> +};
> +
> +U_BOOT_DRIVER(eth_enetc) = {
> +       .name   = "enetc_eth",
> +       .id     = UCLASS_ETH,
> +       .bind   = enetc_bind,
> +       .probe  = enetc_probe,
> +       .ops    = &enetc_ops,
> +       .priv_auto_alloc_size = sizeof(struct enetc_devfn),
> +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +};
> +
> +static struct pci_device_id enetc_ids[] = {
> +       { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_PF) },
> +       {}
> +};
> +
> +U_BOOT_PCI_DEVICE(eth_enetc, enetc_ids);
> diff --git a/drivers/net/fsl_enetc.h b/drivers/net/fsl_enetc.h
> new file mode 100644
> index 0000000000..94f836760a
> --- /dev/null
> +++ b/drivers/net/fsl_enetc.h
> @@ -0,0 +1,172 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * ENETC ethernet controller driver
> + * Copyright 2017-2019 NXP
> + */
> +
> +#ifndef _ENETC_H
> +#define _ENETC_H
> +
> +#include <common.h>

This should be put at the beginning of fsl_enetc.c

> +
> +#define enetc_dbg(dev, fmt, args...)   debug("%s:" fmt, dev->name, ##args)
> +
> +/* ENETC Ethernet controller registers */
> +/* Station interface register offsets */
> +#define ENETC_SIMR             0x00
> +#define  ENETC_SIMR_EN         BIT(31)
> +#define ENETC_SICAR0           0x40
> +/* write cache cfg: snoop, no allocate, data & BD coherent */
> +#define  ENETC_SICAR_WR_CFG    0x6767
> +/* read cache cfg: coherent copy, look up, don't alloc in cache */
> +#define  ENETC_SICAR_RD_CFG    0x27270000
> +#define ENETC_SIROCT           0x300
> +#define ENETC_SIRFRM           0x308
> +#define ENETC_SITOCT           0x320
> +#define ENETC_SITFRM           0x328
> +
> +/* Rx/Tx Buffer Descriptor Ring registers */
> +enum enetc_bdr_type {TX, RX};
> +#define ENETC_BDR(type, n, off)        (0x8000 + (type) * 0x100 + (n) * 0x200 + (off))
> +#define ENETC_BDR_IDX_MASK     0xffff
> +
> +/* Rx BDR reg offsets */
> +#define ENETC_RBMR             0x00
> +#define  ENETC_RBMR_EN         BIT(31)
> +#define ENETC_RBBSR            0x08
> +/* initial consumer index for Rx BDR */
> +#define ENETC_RBCIR            0x0c
> +#define ENETC_RBBAR0           0x10
> +#define ENETC_RBBAR1           0x14
> +#define ENETC_RBPIR            0x18
> +#define ENETC_RBLENR           0x20
> +
> +/* Tx BDR reg offsets */
> +#define ENETC_TBMR             0x00
> +#define  ENETC_TBMR_EN         BIT(31)
> +#define ENETC_TBBAR0           0x10
> +#define ENETC_TBBAR1           0x14
> +#define ENETC_TBPIR            0x18
> +#define ENETC_TBCIR            0x1c
> +#define ENETC_TBLENR           0x20
> +
> +/* Port registers offset */
> +#define ENETC_PORT_REGS_OFF            0x10000
> +#define ENETC_PMR                      0x00000
> +#define  ENETC_PMR_SI0_EN              BIT(16)
> +#define ENETC_PSIPMMR                  0x00018
> +#define ENETC_PSIPMAR0                 0x00100
> +#define ENETC_PSIPMAR1                 0x00104
> +#define ENETC_PSICFGR(n)               (0x00940 + (n) * 0x10)
> +#define  ENETC_PSICFGR_SET_TXBDR(val)  ((val) & 0xff)
> +#define  ENETC_PSICFGR_SET_RXBDR(val)  (((val) & 0xff) << 16)
> +/* MAC configuration */
> +#define ENETC_PM_CC                    0x8008
> +#define  ENETC_PM_CC_DEFAULT           0x810
> +#define  ENETC_PM_CC_RX_TX_EN          0x8813
> +#define ENETC_PM_MAXFRM                        0x8014
> +#define  ENETC_RX_MAXFRM_SIZE          PKTSIZE_ALIGN
> +#define ENETC_PM_IF_MODE               0x8300
> +#define  ENETC_PM_IF_MODE_RG           0x00000004
> +#define  ENETC_PM_IF_MODE_AN_ENA       0x00008000
> +#define  ENETC_PM_IF_IFMODE_MASK       GENMASK(1, 0)
> +#define ENETC_PM_IF_STATUS             0x8304
> +#define  ENETC_PM_IF_STATUS_RGL                0x00008000
> +#define  ENETC_PM_IF_STATUS_RGFD       0x00001000
> +/* Port generic registers */
> +#define ENETC_G_EPFBLPR                        0x10d04
> +#define  ENETC_G_EPFBLPR1_XGMII                0x80000000
> +
> +/* buffer descriptors count must be multiple of 8 and aligned to 128 bytes */
> +#define ENETC_BD_CNT           16
> +#define ENETC_ALIGN            128
> +#define ENETC_RX_MBUFF_SIZE    (ENETC_BD_CNT * ENETC_RX_MAXFRM_SIZE)
> +#define ENETC_BUFF_SIZE                PKTSIZE_ALIGN
> +
> +/* single pair of Rx/Tx rings */
> +#define ENETC_RX_BDR_CNT       1
> +#define ENETC_TX_BDR_CNT       1
> +#define ENETC_RX_BDR_ID                0
> +#define ENETC_TX_BDR_ID                0
> +
> +/* Tx buffer descriptor */
> +struct enetc_tx_bd {
> +       __le64 addr;
> +       __le16 buf_len;
> +       __le16 frm_len;
> +       __le16 err_csum;
> +       __le16 flags;
> +};
> +
> +#define ENETC_TXBD_FLAGS_F     BIT(15)
> +#define ENETC_POLL_TRIES       32000
> +
> +/* Rx buffer descriptor */
> +union enetc_rx_bd {
> +       /* SW provided BD format */
> +       struct {
> +               __le64 addr;
> +               u8 reserved[8];
> +       } w;
> +
> +       /* ENETC returned BD format */
> +       struct {
> +               __le16 inet_csum;
> +               __le16 parse_summary;
> +               __le32 rss_hash;
> +               __le16 buf_len;
> +               __le16 vlan_opt;
> +               union {
> +                       struct {
> +                               __le16 flags;
> +                               __le16 error;
> +                       };
> +                       __le32 lstatus;
> +               };
> +       } r;
> +};
> +
> +#define ENETC_RXBD_STATUS_R(status)            (((status) >> 30) & 0x1)
> +#define ENETC_RXBD_STATUS_F(status)            (((status) >> 31) & 0x1)
> +#define ENETC_RXBD_STATUS_ERRORS(status)       (((status) >> 16) & 0xff)
> +#define ENETC_RXBD_STATUS(flags)               ((flags) << 16)
> +
> +/* Tx/Rx ring info */
> +struct bd_ring {
> +       void *cons_idx;
> +       void *prod_idx;
> +       /* next BD index to use */
> +       int next_prod_idx;
> +       int next_cons_idx;
> +       int bd_count;
> +};
> +
> +/* ENETC HW access info */
> +struct enetc_devfn {
> +       void *regs_base; /* base ENETC registers */
> +       void *port_regs; /* base ENETC port registers */
> +
> +       /* Rx/Tx buffer descriptor rings info */
> +       struct bd_ring tx_bdr;
> +       struct bd_ring rx_bdr;
> +};
> +
> +/* register accessors */
> +#define enetc_read_reg(x)      readl((x))
> +#define enetc_write_reg(x, val)        writel((val), (x))
> +#define enetc_read(hw, off)    enetc_read_reg((hw)->regs_base + (off))
> +#define enetc_write(hw, off, v)        enetc_write_reg((hw)->regs_base + (off), v)
> +
> +/* port register accessors */
> +#define enetc_port_regs(hw, off) ((hw)->port_regs + (off))
> +#define enetc_read_port(hw, off) enetc_read_reg(enetc_port_regs((hw), (off)))
> +#define enetc_write_port(hw, off, v) \
> +                               enetc_write_reg(enetc_port_regs((hw), (off)), v)
> +
> +/* BDR register accessors, see ENETC_BDR() */
> +#define enetc_bdr_read(hw, t, n, off) \
> +                               enetc_read(hw, ENETC_BDR(t, n, off))
> +#define enetc_bdr_write(hw, t, n, off, val) \
> +                               enetc_write(hw, ENETC_BDR(t, n, off), val)
> +
> +#endif /* _ENETC_H */
> diff --git a/include/pci_ids.h b/include/pci_ids.h
> index bd59578ccb..16cf0641c7 100644
> --- a/include/pci_ids.h
> +++ b/include/pci_ids.h
> @@ -2483,6 +2483,7 @@
>  #define PCI_DEVICE_ID_MPC8641          0x7010
>  #define PCI_DEVICE_ID_MPC8641D         0x7011
>  #define PCI_DEVICE_ID_MPC8610          0x7018
> +#define PCI_DEVICE_ID_ENETC_PF         0xE100

nits: suggest we put this macro to fsl_enetc.h, unless other codes
besides the fsl_enetc driver want this macro? And only one ENETC id is
listed here, how about other controllers (PFs)? Does the driver only
support the PF0? If yes, name the macro to PCI_DEVICE_ID_ENETC_PF0.

>
>  #define PCI_VENDOR_ID_PASEMI           0x1959
>

Regards,
Bin


More information about the U-Boot mailing list