Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
0002 /* Copyright 2021 NXP
0003  *
0004  * The Integrated Endpoint Register Block (IERB) is configured by pre-boot
0005  * software and is supposed to be to ENETC what a NVRAM is to a 'real' PCIe
0006  * card. Upon FLR, values from the IERB are transferred to the ENETC PFs, and
0007  * are read-only in the PF memory space.
0008  *
0009  * This driver fixes up the power-on reset values for the ENETC shared FIFO,
0010  * such that the TX and RX allocations are sufficient for jumbo frames, and
0011  * that intelligent FIFO dropping is enabled before the internal data
0012  * structures are corrupted.
0013  *
0014  * Even though not all ports might be used on a given board, we are not
0015  * concerned with partitioning the FIFO, because the default values configure
0016  * no strict reservations, so the entire FIFO can be used by the RX of a single
0017  * port, or the TX of a single port.
0018  */
0019 
0020 #include <linux/io.h>
0021 #include <linux/module.h>
0022 #include <linux/of_device.h>
0023 #include <linux/pci.h>
0024 #include <linux/platform_device.h>
0025 #include "enetc.h"
0026 #include "enetc_ierb.h"
0027 
0028 /* IERB registers */
0029 #define ENETC_IERB_TXMBAR(port)         (((port) * 0x100) + 0x8080)
0030 #define ENETC_IERB_RXMBER(port)         (((port) * 0x100) + 0x8090)
0031 #define ENETC_IERB_RXMBLR(port)         (((port) * 0x100) + 0x8094)
0032 #define ENETC_IERB_RXBCR(port)          (((port) * 0x100) + 0x80a0)
0033 #define ENETC_IERB_TXBCR(port)          (((port) * 0x100) + 0x80a8)
0034 #define ENETC_IERB_FMBDTR           0xa000
0035 
0036 #define ENETC_RESERVED_FOR_ICM          1024
0037 
0038 struct enetc_ierb {
0039     void __iomem *regs;
0040 };
0041 
0042 static void enetc_ierb_write(struct enetc_ierb *ierb, u32 offset, u32 val)
0043 {
0044     iowrite32(val, ierb->regs + offset);
0045 }
0046 
0047 int enetc_ierb_register_pf(struct platform_device *pdev,
0048                struct pci_dev *pf_pdev)
0049 {
0050     struct enetc_ierb *ierb = platform_get_drvdata(pdev);
0051     int port = enetc_pf_to_port(pf_pdev);
0052     u16 tx_credit, rx_credit, tx_alloc;
0053 
0054     if (port < 0)
0055         return -ENODEV;
0056 
0057     if (!ierb)
0058         return -EPROBE_DEFER;
0059 
0060     /* By default, it is recommended to set the Host Transfer Agent
0061      * per port transmit byte credit to "1000 + max_frame_size/2".
0062      * The power-on reset value (1800 bytes) is rounded up to the nearest
0063      * 100 assuming a maximum frame size of 1536 bytes.
0064      */
0065     tx_credit = roundup(1000 + ENETC_MAC_MAXFRM_SIZE / 2, 100);
0066 
0067     /* Internal memory allocated for transmit buffering is guaranteed but
0068      * not reserved; i.e. if the total transmit allocation is not used,
0069      * then the unused portion is not left idle, it can be used for receive
0070      * buffering but it will be reclaimed, if required, from receive by
0071      * intelligently dropping already stored receive frames in the internal
0072      * memory to ensure that the transmit allocation is respected.
0073      *
0074      * PaTXMBAR must be set to a value larger than
0075      *     PaTXBCR + 2 * max_frame_size + 32
0076      * if frame preemption is not enabled, or to
0077      *     2 * PaTXBCR + 2 * p_max_frame_size (pMAC maximum frame size) +
0078      *     2 * np_max_frame_size (eMAC maximum frame size) + 64
0079      * if frame preemption is enabled.
0080      */
0081     tx_alloc = roundup(2 * tx_credit + 4 * ENETC_MAC_MAXFRM_SIZE + 64, 16);
0082 
0083     /* Initial credits, in units of 8 bytes, to the Ingress Congestion
0084      * Manager for the maximum amount of bytes the port is allocated for
0085      * pending traffic.
0086      * It is recommended to set the initial credits to 2 times the maximum
0087      * frame size (2 frames of maximum size).
0088      */
0089     rx_credit = DIV_ROUND_UP(ENETC_MAC_MAXFRM_SIZE * 2, 8);
0090 
0091     enetc_ierb_write(ierb, ENETC_IERB_TXBCR(port), tx_credit);
0092     enetc_ierb_write(ierb, ENETC_IERB_TXMBAR(port), tx_alloc);
0093     enetc_ierb_write(ierb, ENETC_IERB_RXBCR(port), rx_credit);
0094 
0095     return 0;
0096 }
0097 EXPORT_SYMBOL(enetc_ierb_register_pf);
0098 
0099 static int enetc_ierb_probe(struct platform_device *pdev)
0100 {
0101     struct enetc_ierb *ierb;
0102     void __iomem *regs;
0103 
0104     ierb = devm_kzalloc(&pdev->dev, sizeof(*ierb), GFP_KERNEL);
0105     if (!ierb)
0106         return -ENOMEM;
0107 
0108     regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
0109     if (IS_ERR(regs))
0110         return PTR_ERR(regs);
0111 
0112     ierb->regs = regs;
0113 
0114     /* Free buffer depletion threshold in bytes.
0115      * This sets the minimum amount of free buffer memory that should be
0116      * maintained in the datapath sub system, and when the amount of free
0117      * buffer memory falls below this threshold, a depletion indication is
0118      * asserted, which may trigger "intelligent drop" frame releases from
0119      * the ingress queues in the ICM.
0120      * It is recommended to set the free buffer depletion threshold to 1024
0121      * bytes, since the ICM needs some FIFO memory for its own use.
0122      */
0123     enetc_ierb_write(ierb, ENETC_IERB_FMBDTR, ENETC_RESERVED_FOR_ICM);
0124 
0125     platform_set_drvdata(pdev, ierb);
0126 
0127     return 0;
0128 }
0129 
0130 static int enetc_ierb_remove(struct platform_device *pdev)
0131 {
0132     return 0;
0133 }
0134 
0135 static const struct of_device_id enetc_ierb_match[] = {
0136     { .compatible = "fsl,ls1028a-enetc-ierb", },
0137     {},
0138 };
0139 MODULE_DEVICE_TABLE(of, enetc_ierb_match);
0140 
0141 static struct platform_driver enetc_ierb_driver = {
0142     .driver = {
0143         .name = "fsl-enetc-ierb",
0144         .of_match_table = enetc_ierb_match,
0145     },
0146     .probe = enetc_ierb_probe,
0147     .remove = enetc_ierb_remove,
0148 };
0149 
0150 module_platform_driver(enetc_ierb_driver);
0151 
0152 MODULE_DESCRIPTION("NXP ENETC IERB");
0153 MODULE_LICENSE("Dual BSD/GPL");