1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
2 | /* Copyright 2021 NXP |
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/mod_devicetable.h> |
22 | #include <linux/module.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), val: tx_credit); |
92 | enetc_ierb_write(ierb, ENETC_IERB_TXMBAR(port), val: tx_alloc); |
93 | enetc_ierb_write(ierb, ENETC_IERB_RXBCR(port), val: 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(dev: &pdev->dev, size: sizeof(*ierb), GFP_KERNEL); |
105 | if (!ierb) |
106 | return -ENOMEM; |
107 | |
108 | regs = devm_platform_get_and_ioremap_resource(pdev, index: 0, NULL); |
109 | if (IS_ERR(ptr: regs)) |
110 | return PTR_ERR(ptr: 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, data: ierb); |
126 | |
127 | return 0; |
128 | } |
129 | |
130 | static const struct of_device_id enetc_ierb_match[] = { |
131 | { .compatible = "fsl,ls1028a-enetc-ierb" , }, |
132 | {}, |
133 | }; |
134 | MODULE_DEVICE_TABLE(of, enetc_ierb_match); |
135 | |
136 | static struct platform_driver enetc_ierb_driver = { |
137 | .driver = { |
138 | .name = "fsl-enetc-ierb" , |
139 | .of_match_table = enetc_ierb_match, |
140 | }, |
141 | .probe = enetc_ierb_probe, |
142 | }; |
143 | |
144 | module_platform_driver(enetc_ierb_driver); |
145 | |
146 | MODULE_DESCRIPTION("NXP ENETC IERB" ); |
147 | MODULE_LICENSE("Dual BSD/GPL" ); |
148 | |