[U-Boot] [PATCH 1/2 v2] drivers: net: add NXP ENETC ethernet driver
Alexandru Marginean
alexandru.marginean at nxp.com
Tue Jun 11 08:18:15 UTC 2019
Hi Bin,
On 6/10/2019 6:42 AM, Bin Meng wrote:
> 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?
I think the reason why we have this here is mostly related to the early
debug days rather than HW buffer restrictions. I'll look into removing
the rx buffer and I'll move the descriptors to private structure.
>
>> +
>> +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.
Only enetc code uses it, I'm OK to move it. I just went with the flow,
it looks like the PCI IDs are defined here.
There are 4 ENETC PFs on the SoC, and this ID applies to all of them.
They are compatible between each other and probed by the same driver, so
they don't need different IDs.
>
>>
>> #define PCI_VENDOR_ID_PASEMI 0x1959
>>
>
> Regards,
> Bin
>
Thank you!
Alex
More information about the U-Boot
mailing list