linux/drivers/net/ethernet/freescale/enetc/enetc_ierb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
   2/* Copyright 2021 NXP Semiconductors
   3 *
   4 * The Integrated Endpoint Register Block (IERB) is configured by pre-boot
   5 * software and is supposed to be to ENETC what a NVRAM is to a 'real' PCIe
   6 * card. Upon FLR, values from the IERB are transferred to the ENETC PFs, and
   7 * are read-only in the PF memory space.
   8 *
   9 * This driver fixes up the power-on reset values for the ENETC shared FIFO,
  10 * such that the TX and RX allocations are sufficient for jumbo frames, and
  11 * that intelligent FIFO dropping is enabled before the internal data
  12 * structures are corrupted.
  13 *
  14 * Even though not all ports might be used on a given board, we are not
  15 * concerned with partitioning the FIFO, because the default values configure
  16 * no strict reservations, so the entire FIFO can be used by the RX of a single
  17 * port, or the TX of a single port.
  18 */
  19
  20#include <linux/io.h>
  21#include <linux/module.h>
  22#include <linux/of_device.h>
  23#include <linux/pci.h>
  24#include <linux/platform_device.h>
  25#include "enetc.h"
  26#include "enetc_ierb.h"
  27
  28/* IERB registers */
  29#define ENETC_IERB_TXMBAR(port)                 (((port) * 0x100) + 0x8080)
  30#define ENETC_IERB_RXMBER(port)                 (((port) * 0x100) + 0x8090)
  31#define ENETC_IERB_RXMBLR(port)                 (((port) * 0x100) + 0x8094)
  32#define ENETC_IERB_RXBCR(port)                  (((port) * 0x100) + 0x80a0)
  33#define ENETC_IERB_TXBCR(port)                  (((port) * 0x100) + 0x80a8)
  34#define ENETC_IERB_FMBDTR                       0xa000
  35
  36#define ENETC_RESERVED_FOR_ICM                  1024
  37
  38struct enetc_ierb {
  39        void __iomem *regs;
  40};
  41
  42static void enetc_ierb_write(struct enetc_ierb *ierb, u32 offset, u32 val)
  43{
  44        iowrite32(val, ierb->regs + offset);
  45}
  46
  47int enetc_ierb_register_pf(struct platform_device *pdev,
  48                           struct pci_dev *pf_pdev)
  49{
  50        struct enetc_ierb *ierb = platform_get_drvdata(pdev);
  51        int port = enetc_pf_to_port(pf_pdev);
  52        u16 tx_credit, rx_credit, tx_alloc;
  53
  54        if (port < 0)
  55                return -ENODEV;
  56
  57        if (!ierb)
  58                return -EPROBE_DEFER;
  59
  60        /* By default, it is recommended to set the Host Transfer Agent
  61         * per port transmit byte credit to "1000 + max_frame_size/2".
  62         * The power-on reset value (1800 bytes) is rounded up to the nearest
  63         * 100 assuming a maximum frame size of 1536 bytes.
  64         */
  65        tx_credit = roundup(1000 + ENETC_MAC_MAXFRM_SIZE / 2, 100);
  66
  67        /* Internal memory allocated for transmit buffering is guaranteed but
  68         * not reserved; i.e. if the total transmit allocation is not used,
  69         * then the unused portion is not left idle, it can be used for receive
  70         * buffering but it will be reclaimed, if required, from receive by
  71         * intelligently dropping already stored receive frames in the internal
  72         * memory to ensure that the transmit allocation is respected.
  73         *
  74         * PaTXMBAR must be set to a value larger than
  75         *     PaTXBCR + 2 * max_frame_size + 32
  76         * if frame preemption is not enabled, or to
  77         *     2 * PaTXBCR + 2 * p_max_frame_size (pMAC maximum frame size) +
  78         *     2 * np_max_frame_size (eMAC maximum frame size) + 64
  79         * if frame preemption is enabled.
  80         */
  81        tx_alloc = roundup(2 * tx_credit + 4 * ENETC_MAC_MAXFRM_SIZE + 64, 16);
  82
  83        /* Initial credits, in units of 8 bytes, to the Ingress Congestion
  84         * Manager for the maximum amount of bytes the port is allocated for
  85         * pending traffic.
  86         * It is recommended to set the initial credits to 2 times the maximum
  87         * frame size (2 frames of maximum size).
  88         */
  89        rx_credit = DIV_ROUND_UP(ENETC_MAC_MAXFRM_SIZE * 2, 8);
  90
  91        enetc_ierb_write(ierb, ENETC_IERB_TXBCR(port), tx_credit);
  92        enetc_ierb_write(ierb, ENETC_IERB_TXMBAR(port), tx_alloc);
  93        enetc_ierb_write(ierb, ENETC_IERB_RXBCR(port), rx_credit);
  94
  95        return 0;
  96}
  97EXPORT_SYMBOL(enetc_ierb_register_pf);
  98
  99static int enetc_ierb_probe(struct platform_device *pdev)
 100{
 101        struct enetc_ierb *ierb;
 102        struct resource *res;
 103        void __iomem *regs;
 104
 105        ierb = devm_kzalloc(&pdev->dev, sizeof(*ierb), GFP_KERNEL);
 106        if (!ierb)
 107                return -ENOMEM;
 108
 109        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 110        regs = devm_ioremap_resource(&pdev->dev, res);
 111        if (IS_ERR(regs))
 112                return PTR_ERR(regs);
 113
 114        ierb->regs = regs;
 115
 116        /* Free buffer depletion threshold in bytes.
 117         * This sets the minimum amount of free buffer memory that should be
 118         * maintained in the datapath sub system, and when the amount of free
 119         * buffer memory falls below this threshold, a depletion indication is
 120         * asserted, which may trigger "intelligent drop" frame releases from
 121         * the ingress queues in the ICM.
 122         * It is recommended to set the free buffer depletion threshold to 1024
 123         * bytes, since the ICM needs some FIFO memory for its own use.
 124         */
 125        enetc_ierb_write(ierb, ENETC_IERB_FMBDTR, ENETC_RESERVED_FOR_ICM);
 126
 127        platform_set_drvdata(pdev, ierb);
 128
 129        return 0;
 130}
 131
 132static int enetc_ierb_remove(struct platform_device *pdev)
 133{
 134        return 0;
 135}
 136
 137static const struct of_device_id enetc_ierb_match[] = {
 138        { .compatible = "fsl,ls1028a-enetc-ierb", },
 139        {},
 140};
 141MODULE_DEVICE_TABLE(of, enetc_ierb_match);
 142
 143static struct platform_driver enetc_ierb_driver = {
 144        .driver = {
 145                .name = "fsl-enetc-ierb",
 146                .of_match_table = enetc_ierb_match,
 147        },
 148        .probe = enetc_ierb_probe,
 149        .remove = enetc_ierb_remove,
 150};
 151
 152module_platform_driver(enetc_ierb_driver);
 153
 154MODULE_DESCRIPTION("NXP ENETC IERB");
 155MODULE_LICENSE("Dual BSD/GPL");
 156