xref: /linux/drivers/net/ethernet/freescale/enetc/enetc_ierb.c (revision 6beeaf48db6c548fcfc2ad32739d33af2fef3a5b)
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 
38 struct enetc_ierb {
39 	void __iomem *regs;
40 };
41 
42 static void enetc_ierb_write(struct enetc_ierb *ierb, u32 offset, u32 val)
43 {
44 	iowrite32(val, ierb->regs + offset);
45 }
46 
47 int 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 }
97 EXPORT_SYMBOL(enetc_ierb_register_pf);
98 
99 static int enetc_ierb_probe(struct platform_device *pdev)
100 {
101 	struct enetc_ierb *ierb;
102 	void __iomem *regs;
103 
104 	ierb = devm_kzalloc(&pdev->dev, sizeof(*ierb), GFP_KERNEL);
105 	if (!ierb)
106 		return -ENOMEM;
107 
108 	regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
109 	if (IS_ERR(regs))
110 		return PTR_ERR(regs);
111 
112 	ierb->regs = regs;
113 
114 	/* Free buffer depletion threshold in bytes.
115 	 * This sets the minimum amount of free buffer memory that should be
116 	 * maintained in the datapath sub system, and when the amount of free
117 	 * buffer memory falls below this threshold, a depletion indication is
118 	 * asserted, which may trigger "intelligent drop" frame releases from
119 	 * the ingress queues in the ICM.
120 	 * It is recommended to set the free buffer depletion threshold to 1024
121 	 * bytes, since the ICM needs some FIFO memory for its own use.
122 	 */
123 	enetc_ierb_write(ierb, ENETC_IERB_FMBDTR, ENETC_RESERVED_FOR_ICM);
124 
125 	platform_set_drvdata(pdev, ierb);
126 
127 	return 0;
128 }
129 
130 static int enetc_ierb_remove(struct platform_device *pdev)
131 {
132 	return 0;
133 }
134 
135 static const struct of_device_id enetc_ierb_match[] = {
136 	{ .compatible = "fsl,ls1028a-enetc-ierb", },
137 	{},
138 };
139 MODULE_DEVICE_TABLE(of, enetc_ierb_match);
140 
141 static struct platform_driver enetc_ierb_driver = {
142 	.driver = {
143 		.name = "fsl-enetc-ierb",
144 		.of_match_table = enetc_ierb_match,
145 	},
146 	.probe = enetc_ierb_probe,
147 	.remove = enetc_ierb_remove,
148 };
149 
150 module_platform_driver(enetc_ierb_driver);
151 
152 MODULE_DESCRIPTION("NXP ENETC IERB");
153 MODULE_LICENSE("Dual BSD/GPL");
154