1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
61
62
63
64
65 tx_credit = roundup(1000 + ENETC_MAC_MAXFRM_SIZE / 2, 100);
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 tx_alloc = roundup(2 * tx_credit + 4 * ENETC_MAC_MAXFRM_SIZE + 64, 16);
82
83
84
85
86
87
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
117
118
119
120
121
122
123
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