dca205e0ef7521d47b1d7854290554a5a97ba6f1
[platform/kernel/linux-rpi.git] / drivers / net / ethernet / mscc / ocelot_board.c
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /*
3  * Microsemi Ocelot Switch driver
4  *
5  * Copyright (c) 2017 Microsemi Corporation
6  */
7 #include <linux/interrupt.h>
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10 #include <linux/of_mdio.h>
11 #include <linux/of_platform.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/skbuff.h>
14
15 #include "ocelot.h"
16
17 static int ocelot_parse_ifh(u32 *ifh, struct frame_info *info)
18 {
19         int i;
20         u8 llen, wlen;
21
22         /* The IFH is in network order, switch to CPU order */
23         for (i = 0; i < IFH_LEN; i++)
24                 ifh[i] = ntohl((__force __be32)ifh[i]);
25
26         wlen = (ifh[1] >> 7) & 0xff;
27         llen = (ifh[1] >> 15) & 0x3f;
28         info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80;
29
30         info->port = (ifh[2] & GENMASK(14, 11)) >> 11;
31
32         info->cpuq = (ifh[3] & GENMASK(27, 20)) >> 20;
33         info->tag_type = (ifh[3] & BIT(16)) >> 16;
34         info->vid = ifh[3] & GENMASK(11, 0);
35
36         return 0;
37 }
38
39 static int ocelot_rx_frame_word(struct ocelot *ocelot, u8 grp, bool ifh,
40                                 u32 *rval)
41 {
42         u32 val;
43         u32 bytes_valid;
44
45         val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
46         if (val == XTR_NOT_READY) {
47                 if (ifh)
48                         return -EIO;
49
50                 do {
51                         val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
52                 } while (val == XTR_NOT_READY);
53         }
54
55         switch (val) {
56         case XTR_ABORT:
57                 return -EIO;
58         case XTR_EOF_0:
59         case XTR_EOF_1:
60         case XTR_EOF_2:
61         case XTR_EOF_3:
62         case XTR_PRUNED:
63                 bytes_valid = XTR_VALID_BYTES(val);
64                 val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
65                 if (val == XTR_ESCAPE)
66                         *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
67                 else
68                         *rval = val;
69
70                 return bytes_valid;
71         case XTR_ESCAPE:
72                 *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
73
74                 return 4;
75         default:
76                 *rval = val;
77
78                 return 4;
79         }
80 }
81
82 static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
83 {
84         struct ocelot *ocelot = arg;
85         int i = 0, grp = 0;
86         int err = 0;
87
88         if (!(ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)))
89                 return IRQ_NONE;
90
91         do {
92                 struct sk_buff *skb;
93                 struct net_device *dev;
94                 u32 *buf;
95                 int sz, len, buf_len;
96                 u32 ifh[4];
97                 u32 val;
98                 struct frame_info info;
99
100                 for (i = 0; i < IFH_LEN; i++) {
101                         err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]);
102                         if (err != 4)
103                                 break;
104                 }
105
106                 if (err != 4)
107                         break;
108
109                 ocelot_parse_ifh(ifh, &info);
110
111                 dev = ocelot->ports[info.port]->dev;
112
113                 skb = netdev_alloc_skb(dev, info.len);
114
115                 if (unlikely(!skb)) {
116                         netdev_err(dev, "Unable to allocate sk_buff\n");
117                         err = -ENOMEM;
118                         break;
119                 }
120                 buf_len = info.len - ETH_FCS_LEN;
121                 buf = (u32 *)skb_put(skb, buf_len);
122
123                 len = 0;
124                 do {
125                         sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
126                         *buf++ = val;
127                         len += sz;
128                 } while (len < buf_len);
129
130                 /* Read the FCS and discard it */
131                 sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
132                 /* Update the statistics if part of the FCS was read before */
133                 len -= ETH_FCS_LEN - sz;
134
135                 if (sz < 0) {
136                         err = sz;
137                         break;
138                 }
139
140                 /* Everything we see on an interface that is in the HW bridge
141                  * has already been forwarded.
142                  */
143                 if (ocelot->bridge_mask & BIT(info.port))
144                         skb->offload_fwd_mark = 1;
145
146                 skb->protocol = eth_type_trans(skb, dev);
147                 netif_rx(skb);
148                 dev->stats.rx_bytes += len;
149                 dev->stats.rx_packets++;
150         } while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp));
151
152         if (err)
153                 while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp))
154                         ocelot_read_rix(ocelot, QS_XTR_RD, grp);
155
156         return IRQ_HANDLED;
157 }
158
159 static const struct of_device_id mscc_ocelot_match[] = {
160         { .compatible = "mscc,vsc7514-switch" },
161         { }
162 };
163 MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
164
165 static int mscc_ocelot_probe(struct platform_device *pdev)
166 {
167         int err, irq;
168         unsigned int i;
169         struct device_node *np = pdev->dev.of_node;
170         struct device_node *ports, *portnp;
171         struct ocelot *ocelot;
172         struct regmap *hsio;
173         u32 val;
174
175         struct {
176                 enum ocelot_target id;
177                 char *name;
178         } res[] = {
179                 { SYS, "sys" },
180                 { REW, "rew" },
181                 { QSYS, "qsys" },
182                 { ANA, "ana" },
183                 { QS, "qs" },
184         };
185
186         if (!np && !pdev->dev.platform_data)
187                 return -ENODEV;
188
189         ocelot = devm_kzalloc(&pdev->dev, sizeof(*ocelot), GFP_KERNEL);
190         if (!ocelot)
191                 return -ENOMEM;
192
193         platform_set_drvdata(pdev, ocelot);
194         ocelot->dev = &pdev->dev;
195
196         for (i = 0; i < ARRAY_SIZE(res); i++) {
197                 struct regmap *target;
198
199                 target = ocelot_io_platform_init(ocelot, pdev, res[i].name);
200                 if (IS_ERR(target))
201                         return PTR_ERR(target);
202
203                 ocelot->targets[res[i].id] = target;
204         }
205
206         hsio = syscon_regmap_lookup_by_compatible("mscc,ocelot-hsio");
207         if (IS_ERR(hsio)) {
208                 dev_err(&pdev->dev, "missing hsio syscon\n");
209                 return PTR_ERR(hsio);
210         }
211
212         ocelot->targets[HSIO] = hsio;
213
214         err = ocelot_chip_init(ocelot);
215         if (err)
216                 return err;
217
218         irq = platform_get_irq_byname(pdev, "xtr");
219         if (irq < 0)
220                 return -ENODEV;
221
222         err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
223                                         ocelot_xtr_irq_handler, IRQF_ONESHOT,
224                                         "frame extraction", ocelot);
225         if (err)
226                 return err;
227
228         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
229         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
230
231         do {
232                 msleep(1);
233                 regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
234                                   &val);
235         } while (val);
236
237         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
238         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
239
240         ocelot->num_cpu_ports = 1; /* 1 port on the switch, two groups */
241
242         ports = of_get_child_by_name(np, "ethernet-ports");
243         if (!ports) {
244                 dev_err(&pdev->dev, "no ethernet-ports child node found\n");
245                 return -ENODEV;
246         }
247
248         ocelot->num_phys_ports = of_get_child_count(ports);
249
250         ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
251                                      sizeof(struct ocelot_port *), GFP_KERNEL);
252
253         INIT_LIST_HEAD(&ocelot->multicast);
254         ocelot_init(ocelot);
255
256         ocelot_rmw(ocelot, HSIO_HW_CFG_DEV1G_4_MODE |
257                      HSIO_HW_CFG_DEV1G_6_MODE |
258                      HSIO_HW_CFG_DEV1G_9_MODE,
259                      HSIO_HW_CFG_DEV1G_4_MODE |
260                      HSIO_HW_CFG_DEV1G_6_MODE |
261                      HSIO_HW_CFG_DEV1G_9_MODE,
262                      HSIO_HW_CFG);
263
264         for_each_available_child_of_node(ports, portnp) {
265                 struct device_node *phy_node;
266                 struct phy_device *phy;
267                 struct resource *res;
268                 void __iomem *regs;
269                 char res_name[8];
270                 u32 port;
271
272                 if (of_property_read_u32(portnp, "reg", &port))
273                         continue;
274
275                 snprintf(res_name, sizeof(res_name), "port%d", port);
276
277                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
278                                                    res_name);
279                 regs = devm_ioremap_resource(&pdev->dev, res);
280                 if (IS_ERR(regs))
281                         continue;
282
283                 phy_node = of_parse_phandle(portnp, "phy-handle", 0);
284                 if (!phy_node)
285                         continue;
286
287                 phy = of_phy_find_device(phy_node);
288                 if (!phy)
289                         continue;
290
291                 err = ocelot_probe_port(ocelot, port, regs, phy);
292                 if (err) {
293                         dev_err(&pdev->dev, "failed to probe ports\n");
294                         goto err_probe_ports;
295                 }
296         }
297
298         register_netdevice_notifier(&ocelot_netdevice_nb);
299
300         dev_info(&pdev->dev, "Ocelot switch probed\n");
301
302         return 0;
303
304 err_probe_ports:
305         return err;
306 }
307
308 static int mscc_ocelot_remove(struct platform_device *pdev)
309 {
310         struct ocelot *ocelot = platform_get_drvdata(pdev);
311
312         ocelot_deinit(ocelot);
313         unregister_netdevice_notifier(&ocelot_netdevice_nb);
314
315         return 0;
316 }
317
318 static struct platform_driver mscc_ocelot_driver = {
319         .probe = mscc_ocelot_probe,
320         .remove = mscc_ocelot_remove,
321         .driver = {
322                 .name = "ocelot-switch",
323                 .of_match_table = mscc_ocelot_match,
324         },
325 };
326
327 module_platform_driver(mscc_ocelot_driver);
328
329 MODULE_DESCRIPTION("Microsemi Ocelot switch driver");
330 MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
331 MODULE_LICENSE("Dual MIT/GPL");